eval.c (23840B)
1 #include <assert.h> 2 #include <stdbool.h> 3 #include <stdint.h> 4 #include <stdlib.h> 5 #include <string.h> 6 #include "check.h" 7 #include "eval.h" 8 #include "expr.h" 9 #include "scope.h" 10 #include "type_store.h" 11 #include "types.h" 12 #include "util.h" 13 14 static enum eval_result 15 eval_access(struct context *ctx, struct expression *in, struct expression *out) 16 { 17 struct expression tmp = {0}; 18 enum eval_result r; 19 20 switch (in->access.type) { 21 case ACCESS_IDENTIFIER: 22 return EVAL_INVALID; // &ident handled in eval_unarithm 23 case ACCESS_INDEX: 24 r = eval_expr(ctx, in->access.array, &tmp); 25 if (r != EVAL_OK) { 26 return r; 27 } 28 const struct array_constant *array = tmp.constant.array; 29 r = eval_expr(ctx, in->access.index, &tmp); 30 if (r != EVAL_OK) { 31 return r; 32 } 33 for (size_t i = tmp.constant.uval; i > 0; --i) { 34 if (array == NULL) { 35 // out of bounds 36 return EVAL_INVALID; 37 } 38 array = array->next; 39 } 40 return eval_expr(ctx, array->value, out); 41 case ACCESS_FIELD: 42 r = eval_expr(ctx, in->access._struct, &tmp); 43 if (r != EVAL_OK) { 44 return r; 45 } 46 const struct struct_constant *fields = tmp.constant._struct; 47 for (; fields != NULL; fields = fields->next) { 48 if (!strcmp(fields->field->name, in->access.field->name)) { 49 break; 50 } 51 } 52 if (fields == NULL) { 53 return EVAL_INVALID; 54 } 55 return eval_expr(ctx, fields->value, out); 56 case ACCESS_TUPLE: 57 r = eval_expr(ctx, in->access.tuple, &tmp); 58 if (r != EVAL_OK) { 59 return r; 60 } 61 const struct tuple_constant *tuple = tmp.constant.tuple; 62 for (size_t i = in->access.tindex; i > 0; --i) { 63 if (tuple == NULL) { 64 // out of bounds 65 return EVAL_INVALID; 66 } 67 tuple = tuple->next; 68 } 69 return eval_expr(ctx, tuple->value, out); 70 } 71 72 return EVAL_OK; 73 } 74 75 static uintmax_t 76 itrunc(const struct type *type, uintmax_t val) 77 { 78 switch (type->storage) { 79 case STORAGE_CHAR: 80 case STORAGE_U8: 81 return (uint8_t)val; 82 case STORAGE_U16: 83 return (uint16_t)val; 84 case STORAGE_U32: 85 case STORAGE_RCONST: 86 case STORAGE_RUNE: 87 return (uint32_t)val; 88 case STORAGE_U64: 89 return (uint64_t)val; 90 case STORAGE_I8: 91 return (int8_t)((val >> 24) | (val & 0x7F)); 92 case STORAGE_I16: 93 return (int16_t)((val >> 16) | (val & 0x7FF)); 94 case STORAGE_I32: 95 return (int32_t)((val >> 8) | (val & 0x7FFFF)); 96 case STORAGE_I64: 97 return (int64_t)val; 98 case STORAGE_INT: 99 return (int)val; 100 case STORAGE_UINT: 101 return (unsigned int)val; 102 case STORAGE_ARRAY: 103 case STORAGE_ICONST: 104 case STORAGE_POINTER: 105 case STORAGE_SIZE: 106 case STORAGE_UINTPTR: 107 return val; 108 case STORAGE_BOOL: 109 return (bool)val; 110 case STORAGE_NULL: 111 return (uintptr_t)NULL; 112 case STORAGE_ALIAS: 113 return itrunc(type_dealias(type), val); 114 case STORAGE_ENUM: 115 return itrunc(type->alias.type, val); 116 case STORAGE_F32: 117 case STORAGE_F64: 118 case STORAGE_FCONST: 119 case STORAGE_FUNCTION: 120 case STORAGE_SLICE: 121 case STORAGE_STRING: 122 case STORAGE_STRUCT: 123 case STORAGE_TAGGED: 124 case STORAGE_TUPLE: 125 case STORAGE_UNION: 126 case STORAGE_VALIST: 127 case STORAGE_VOID: 128 assert(0); 129 } 130 assert(0); 131 } 132 133 static double 134 ftrunc(const struct type *type, double val) 135 { 136 if (type->storage == STORAGE_F32) { 137 return (float)val; 138 } 139 assert(type_is_float(type)); 140 return val; 141 } 142 143 enum eval_result 144 eval_binarithm(struct context *ctx, struct expression *in, struct expression *out) 145 { 146 struct expression lvalue = {0}, rvalue = {0}; 147 enum eval_result r = eval_expr(ctx, in->binarithm.lvalue, &lvalue); 148 if (r != EVAL_OK) { 149 return r; 150 } 151 r = eval_expr(ctx, in->binarithm.rvalue, &rvalue); 152 if (r != EVAL_OK) { 153 return r; 154 } 155 156 bool blval = lvalue.constant.bval, brval = rvalue.constant.bval, bval; 157 intmax_t ilval = lvalue.constant.ival, irval = rvalue.constant.ival, ival; 158 uintmax_t ulval = lvalue.constant.uval, urval = rvalue.constant.uval, uval; 159 double flval = lvalue.constant.fval, frval = rvalue.constant.fval, fval; 160 // Type promotion is lowered in check 161 assert(lvalue.result->storage == rvalue.result->storage); 162 switch (in->binarithm.op) { 163 case BIN_BAND: 164 assert(!type_is_float(lvalue.result)); 165 if (type_is_signed(lvalue.result)) { 166 ival = itrunc(lvalue.result, ilval) & itrunc(rvalue.result, irval); 167 } else { 168 uval = itrunc(lvalue.result, ulval) & itrunc(rvalue.result, urval); 169 } 170 break; 171 case BIN_BOR: 172 assert(!type_is_float(lvalue.result)); 173 if (type_is_signed(lvalue.result)) { 174 ival = itrunc(lvalue.result, ilval) | itrunc(rvalue.result, irval); 175 } else { 176 uval = itrunc(lvalue.result, ulval) | itrunc(rvalue.result, urval); 177 } 178 break; 179 case BIN_DIV: 180 if (type_is_float(lvalue.result)) { 181 fval = ftrunc(lvalue.result, flval) / ftrunc(rvalue.result, frval); 182 } else if (type_is_signed(lvalue.result)) { 183 uintmax_t r = itrunc(rvalue.result, irval); 184 if (r == 0) { 185 return EVAL_INVALID; 186 } 187 ival = itrunc(lvalue.result, ilval) / r; 188 } else { 189 uintmax_t r = itrunc(rvalue.result, urval); 190 if (r == 0) { 191 return EVAL_INVALID; 192 } 193 uval = itrunc(lvalue.result, ulval) / r; 194 } 195 break; 196 case BIN_LSHIFT: 197 assert(!type_is_signed(rvalue.result)); 198 assert(!type_is_float(lvalue.result)); 199 uval = itrunc(lvalue.result, ulval) << itrunc(rvalue.result, urval); 200 break; 201 case BIN_MINUS: 202 if (type_is_float(lvalue.result)) { 203 fval = ftrunc(lvalue.result, flval) - ftrunc(rvalue.result, frval); 204 } else if (type_is_signed(lvalue.result)) { 205 ival = itrunc(lvalue.result, ilval) - itrunc(rvalue.result, irval); 206 } else { 207 uval = itrunc(lvalue.result, ulval) - itrunc(rvalue.result, urval); 208 } 209 break; 210 case BIN_MODULO: 211 assert(!type_is_float(lvalue.result)); 212 if (type_is_signed(lvalue.result)) { 213 uintmax_t r = itrunc(rvalue.result, irval); 214 if (r == 0) { 215 return EVAL_INVALID; 216 } 217 ival = itrunc(lvalue.result, ilval) % itrunc(rvalue.result, irval); 218 } else { 219 uintmax_t r = itrunc(rvalue.result, urval); 220 if (r == 0) { 221 return EVAL_INVALID; 222 } 223 uval = itrunc(lvalue.result, ulval) % itrunc(rvalue.result, urval); 224 } 225 break; 226 case BIN_PLUS: 227 if (type_is_float(lvalue.result)) { 228 fval = ftrunc(lvalue.result, flval) + ftrunc(rvalue.result, frval); 229 } else if (type_is_signed(lvalue.result)) { 230 ival = itrunc(lvalue.result, ilval) + itrunc(rvalue.result, irval); 231 } else { 232 uval = itrunc(lvalue.result, ulval) + itrunc(rvalue.result, urval); 233 } 234 break; 235 case BIN_RSHIFT: 236 assert(!type_is_signed(rvalue.result)); 237 assert(!type_is_float(lvalue.result)); 238 uval = itrunc(lvalue.result, ulval) >> itrunc(rvalue.result, urval); 239 break; 240 case BIN_TIMES: 241 if (type_is_float(lvalue.result)) { 242 fval = ftrunc(lvalue.result, flval) * ftrunc(rvalue.result, frval); 243 } else if (type_is_signed(lvalue.result)) { 244 ival = itrunc(lvalue.result, ilval) * itrunc(rvalue.result, irval); 245 } else { 246 uval = itrunc(lvalue.result, ulval) * itrunc(rvalue.result, urval); 247 } 248 break; 249 case BIN_BXOR: 250 assert(!type_is_float(lvalue.result)); 251 if (type_is_signed(lvalue.result)) { 252 ival = itrunc(lvalue.result, ilval) ^ itrunc(rvalue.result, irval); 253 } else { 254 uval = itrunc(lvalue.result, ulval) ^ itrunc(rvalue.result, urval); 255 } 256 break; 257 // Logical arithmetic 258 case BIN_GREATER: 259 if (type_is_float(lvalue.result)) { 260 bval = ftrunc(lvalue.result, flval) > ftrunc(rvalue.result, frval); 261 } else if (type_is_signed(lvalue.result)) { 262 bval = itrunc(lvalue.result, ilval) > itrunc(rvalue.result, irval); 263 } else { 264 bval = itrunc(lvalue.result, ulval) > itrunc(rvalue.result, urval); 265 } 266 break; 267 case BIN_GREATEREQ: 268 if (type_is_float(lvalue.result)) { 269 bval = ftrunc(lvalue.result, flval) >= ftrunc(rvalue.result, frval); 270 } else if (type_is_signed(lvalue.result)) { 271 bval = itrunc(lvalue.result, ilval) >= itrunc(rvalue.result, irval); 272 } else { 273 bval = itrunc(lvalue.result, ulval) >= itrunc(rvalue.result, urval); 274 } 275 break; 276 case BIN_LAND: 277 assert(type_dealias(lvalue.result)->storage == STORAGE_BOOL 278 && type_dealias(rvalue.result)->storage == STORAGE_BOOL); 279 bval = blval && brval; 280 break; 281 case BIN_LEQUAL: 282 if (type_is_float(lvalue.result)) { 283 bval = ftrunc(lvalue.result, flval) == ftrunc(rvalue.result, frval); 284 } else if (type_is_signed(lvalue.result)) { 285 bval = itrunc(lvalue.result, ilval) == itrunc(rvalue.result, irval); 286 } else { 287 bval = itrunc(lvalue.result, ulval) == itrunc(rvalue.result, urval); 288 } 289 break; 290 case BIN_LESS: 291 if (type_is_float(lvalue.result)) { 292 bval = ftrunc(lvalue.result, flval) < ftrunc(rvalue.result, frval); 293 } else if (type_is_signed(lvalue.result)) { 294 bval = itrunc(lvalue.result, ilval) < itrunc(rvalue.result, irval); 295 } else { 296 bval = itrunc(lvalue.result, ulval) < itrunc(rvalue.result, urval); 297 } 298 break; 299 case BIN_LESSEQ: 300 if (type_is_float(lvalue.result)) { 301 bval = ftrunc(lvalue.result, flval) <= ftrunc(rvalue.result, frval); 302 } else if (type_is_signed(lvalue.result)) { 303 bval = itrunc(lvalue.result, ilval) <= itrunc(rvalue.result, irval); 304 } else { 305 bval = itrunc(lvalue.result, ulval) <= itrunc(rvalue.result, urval); 306 } 307 break; 308 case BIN_LOR: 309 assert(type_dealias(lvalue.result)->storage == STORAGE_BOOL 310 && type_dealias(rvalue.result)->storage == STORAGE_BOOL); 311 bval = blval || brval; 312 break; 313 case BIN_LXOR: 314 assert(type_dealias(lvalue.result)->storage == STORAGE_BOOL 315 && type_dealias(rvalue.result)->storage == STORAGE_BOOL); 316 bval = blval != brval; 317 break; 318 case BIN_NEQUAL: 319 if (type_is_float(lvalue.result)) { 320 bval = ftrunc(lvalue.result, flval) != ftrunc(rvalue.result, frval); 321 } else if (type_is_signed(lvalue.result)) { 322 bval = itrunc(lvalue.result, ilval) != itrunc(rvalue.result, irval); 323 } else { 324 bval = itrunc(lvalue.result, ulval) != itrunc(rvalue.result, urval); 325 } 326 break; 327 } 328 if (type_is_float(in->result)) { 329 out->constant.fval = ftrunc(in->result, fval); 330 } else if (type_is_signed(in->result)) { 331 out->constant.ival = itrunc(in->result, ival); 332 } else if (type_dealias(in->result)->storage == STORAGE_BOOL) { 333 out->constant.bval = bval; 334 } else { 335 out->constant.uval = itrunc(in->result, uval); 336 } 337 return EVAL_OK; 338 } 339 340 enum eval_result 341 eval_const(struct context *ctx, struct expression *in, struct expression *out) 342 { 343 enum type_storage storage = type_dealias(out->result)->storage; 344 if (storage == STORAGE_ENUM) { 345 storage = type_dealias(out->result)->alias.type->storage; 346 } 347 struct array_constant **next; 348 switch (storage) { 349 case STORAGE_ALIAS: 350 case STORAGE_ENUM: 351 assert(0); // Handled above 352 case STORAGE_ARRAY: 353 next = &out->constant.array; 354 for (struct array_constant *arr = in->constant.array; arr; 355 arr = arr->next) { 356 struct array_constant *aconst = *next = 357 xcalloc(sizeof(struct array_constant), 1); 358 aconst->value = xcalloc(sizeof(struct expression), 1); 359 eval_expr(ctx, arr->value, aconst->value); 360 next = &aconst->next; 361 } 362 break; 363 case STORAGE_FUNCTION: 364 case STORAGE_SLICE: 365 assert(0); // TODO 366 case STORAGE_STRING: 367 out->constant.string.len = in->constant.string.len; 368 out->constant.string.value = xcalloc(1, in->constant.string.len); 369 memcpy(out->constant.string.value, 370 in->constant.string.value, 371 in->constant.string.len); 372 break; 373 case STORAGE_STRUCT: 374 case STORAGE_UNION: 375 case STORAGE_TAGGED: 376 case STORAGE_TUPLE: 377 assert(0); // TODO 378 case STORAGE_BOOL: 379 case STORAGE_CHAR: 380 case STORAGE_F32: 381 case STORAGE_F64: 382 case STORAGE_FCONST: 383 case STORAGE_I16: 384 case STORAGE_I32: 385 case STORAGE_I64: 386 case STORAGE_I8: 387 case STORAGE_ICONST: 388 case STORAGE_INT: 389 case STORAGE_NULL: 390 case STORAGE_POINTER: 391 case STORAGE_RCONST: 392 case STORAGE_RUNE: 393 case STORAGE_SIZE: 394 case STORAGE_U16: 395 case STORAGE_U32: 396 case STORAGE_U64: 397 case STORAGE_U8: 398 case STORAGE_UINT: 399 case STORAGE_UINTPTR: 400 case STORAGE_VOID: 401 out->constant = in->constant; 402 break; 403 case STORAGE_VALIST: 404 abort(); // Invariant 405 } 406 return EVAL_OK; 407 } 408 409 static void 410 eval_expand_array(struct context *ctx, 411 const struct type *intype, const struct type *outtype, 412 struct expression *in, struct expression *out) 413 { 414 assert(in->type == EXPR_CONSTANT); 415 assert(out->type == EXPR_CONSTANT); 416 assert(intype->storage == STORAGE_ARRAY); 417 assert(outtype->storage == STORAGE_ARRAY); 418 struct array_constant *array_in = in->constant.array; 419 struct array_constant **next = &out->constant.array; 420 for (size_t i = 0; i < outtype->array.length; i++) { 421 struct array_constant *item = *next = 422 xcalloc(1, sizeof(struct array_constant)); 423 item->value = array_in->value; 424 next = &item->next; 425 if (array_in->next) { 426 array_in = array_in->next; 427 } 428 } 429 } 430 431 enum eval_result 432 eval_cast(struct context *ctx, struct expression *in, struct expression *out) 433 { 434 struct expression val = {0}; 435 enum eval_result r = eval_expr(ctx, in->cast.value, &val); 436 if (r != EVAL_OK) { 437 return r; 438 } 439 440 const struct type *to = type_dealias(in->result), 441 *from = type_dealias(val.result); 442 // The STORAGE_ARRAY exception is to make sure we handle expandable 443 // arrays at this point. 444 if (to->storage == from->storage && to->storage != STORAGE_ARRAY) { 445 out->constant = val.constant; 446 return EVAL_OK; 447 } 448 449 // XXX: We should also be able to handle expressions which use 450 // symbols/identifiers 451 452 const struct type *subtype; 453 switch (to->storage) { 454 case STORAGE_POINTER: 455 if (from->storage == STORAGE_NULL) { 456 out->constant.uval = 0; 457 return EVAL_OK; 458 } 459 assert(from->storage == STORAGE_POINTER 460 || from->storage == STORAGE_UINTPTR); 461 out->constant.uval = val.constant.uval; 462 return EVAL_OK; 463 case STORAGE_ENUM: 464 case STORAGE_I16: 465 case STORAGE_I32: 466 case STORAGE_I64: 467 case STORAGE_I8: 468 case STORAGE_ICONST: 469 case STORAGE_INT: 470 case STORAGE_U16: 471 case STORAGE_U32: 472 case STORAGE_U64: 473 case STORAGE_U8: 474 case STORAGE_UINT: 475 case STORAGE_UINTPTR: 476 case STORAGE_SIZE: 477 case STORAGE_RCONST: 478 case STORAGE_RUNE: 479 if (type_is_float(val.result)) { 480 out->constant.ival = 481 itrunc(to, (intmax_t)val.constant.fval); 482 } else if (type_is_signed(val.result)) { 483 out->constant.ival = itrunc(to, val.constant.ival); 484 } else { 485 out->constant.ival = itrunc(to, val.constant.uval); 486 } 487 return EVAL_OK; 488 case STORAGE_ARRAY: 489 assert(from->storage == STORAGE_ARRAY); 490 if (from->array.expandable) { 491 eval_expand_array(ctx, from, to, &val, out); 492 } else { 493 out->constant = val.constant; 494 } 495 return EVAL_OK; 496 case STORAGE_SLICE: 497 assert(val.result->storage == STORAGE_ARRAY); 498 out->constant = val.constant; 499 return EVAL_OK; 500 case STORAGE_F32: 501 case STORAGE_F64: 502 case STORAGE_FCONST: 503 if (type_is_float(val.result)) { 504 out->constant.fval = ftrunc(to, val.constant.fval); 505 } else if (type_is_signed(val.result)) { 506 out->constant.fval = 507 ftrunc(to, (double)val.constant.ival); 508 } else { 509 out->constant.fval = 510 ftrunc(to, (double)val.constant.uval); 511 } 512 return EVAL_OK; 513 case STORAGE_TAGGED: 514 subtype = tagged_select_subtype(to, val.result); 515 out->constant.tagged.value = 516 xcalloc(1, sizeof(struct expression)); 517 if (subtype) { 518 out->constant.tagged.tag = subtype; 519 *out->constant.tagged.value = val; 520 } else { 521 out->constant.tagged.tag = from; 522 *out->constant.tagged.value = val; 523 } 524 return EVAL_OK; 525 case STORAGE_CHAR: 526 case STORAGE_NULL: 527 case STORAGE_ALIAS: 528 assert(0); // Handled above 529 case STORAGE_BOOL: 530 case STORAGE_FUNCTION: 531 case STORAGE_STRING: 532 case STORAGE_STRUCT: 533 case STORAGE_TUPLE: 534 case STORAGE_UNION: 535 case STORAGE_VALIST: 536 assert(0); // Invariant 537 case STORAGE_VOID: 538 break; // no-op 539 } 540 541 assert(0); // Unreachable 542 } 543 544 enum eval_result 545 eval_measurement(struct context *ctx, struct expression *in, struct expression *out) 546 { 547 assert(in->type == EXPR_MEASURE); 548 struct expression obj = {0}; 549 enum eval_result res; 550 switch (in->measure.op) { 551 case M_LEN: 552 res = eval_expr(ctx, in->measure.value, &obj); 553 if (res != EVAL_OK) { 554 return res; 555 } 556 557 switch (obj.result->storage) { 558 case STORAGE_ARRAY: 559 case STORAGE_SLICE: 560 break; 561 case STORAGE_STRING: 562 out->constant.uval = obj.constant.string.len; 563 return EVAL_OK; 564 default: 565 abort(); // Invariant 566 } 567 568 uintmax_t len = 0; 569 for (struct array_constant *c = obj.constant.array; 570 c != NULL; c = c->next) { 571 len++; 572 } 573 out->constant.uval = len; 574 return EVAL_OK; 575 case M_SIZE: 576 out->constant.uval = in->measure.dimensions.size; 577 return EVAL_OK; 578 case M_OFFSET: 579 if (in->measure.value->access.type == ACCESS_FIELD) { 580 out->constant.uval = 581 in->measure.value->access.field->offset; 582 } else { 583 assert(in->measure.value->access.type == ACCESS_TUPLE); 584 out->constant.uval = 585 in->measure.value->access.tvalue->offset; 586 } 587 return EVAL_OK; 588 } 589 assert(0); 590 } 591 592 static void 593 constant_default(struct context *ctx, struct expression *v) 594 { 595 struct expression b = {0}; 596 switch (type_dealias(v->result)->storage) { 597 case STORAGE_POINTER: 598 case STORAGE_I16: 599 case STORAGE_I32: 600 case STORAGE_I64: 601 case STORAGE_I8: 602 case STORAGE_ICONST: 603 case STORAGE_INT: 604 case STORAGE_U16: 605 case STORAGE_U32: 606 case STORAGE_U64: 607 case STORAGE_U8: 608 case STORAGE_UINT: 609 case STORAGE_UINTPTR: 610 case STORAGE_SIZE: 611 case STORAGE_F32: 612 case STORAGE_F64: 613 case STORAGE_FCONST: 614 case STORAGE_CHAR: 615 case STORAGE_ENUM: 616 case STORAGE_NULL: 617 case STORAGE_RCONST: 618 case STORAGE_RUNE: 619 case STORAGE_SLICE: 620 case STORAGE_BOOL: 621 break; // calloc does this for us 622 case STORAGE_STRUCT: 623 case STORAGE_UNION: 624 b.type = EXPR_STRUCT; 625 b.result = v->result; 626 b._struct.autofill = true; 627 enum eval_result r = eval_expr(ctx, &b, v); 628 assert(r == EVAL_OK); 629 break; 630 case STORAGE_STRING: 631 v->constant.string.value = NULL; 632 v->constant.string.len = 0; 633 break; 634 case STORAGE_ARRAY: 635 v->constant.array = xcalloc(1, sizeof(struct array_constant)); 636 v->constant.array->value = xcalloc(1, sizeof(struct expression)); 637 v->constant.array->value->type = EXPR_CONSTANT; 638 v->constant.array->value->result = 639 type_dealias(v->result)->array.members; 640 constant_default(ctx, v->constant.array->value); 641 break; 642 case STORAGE_TAGGED: 643 case STORAGE_TUPLE: 644 assert(0); // TODO 645 case STORAGE_ALIAS: 646 case STORAGE_FUNCTION: 647 case STORAGE_VALIST: 648 assert(0); // Invariant 649 case STORAGE_VOID: 650 break; // no-op 651 } 652 } 653 654 static int 655 field_compar(const void *_a, const void *_b) 656 { 657 const struct struct_constant **a = (const struct struct_constant **)_a; 658 const struct struct_constant **b = (const struct struct_constant **)_b; 659 return (*a)->field->offset - (*b)->field->offset; 660 } 661 662 static size_t 663 count_struct_fields(const struct type *type) 664 { 665 size_t n = 0; 666 assert(type->storage == STORAGE_STRUCT || type->storage == STORAGE_UNION); 667 for (const struct struct_field *field = type->struct_union.fields; 668 field; field = field->next) { 669 if (!field->name) { 670 n += count_struct_fields(type_dealias(field->type)); 671 } else { 672 ++n; 673 } 674 } 675 return n; 676 } 677 678 void 679 autofill_struct(struct context *ctx, const struct type *type, struct struct_constant **fields) 680 { 681 assert(type->storage == STORAGE_STRUCT || type->storage == STORAGE_UNION); 682 for (const struct struct_field *field = type->struct_union.fields; 683 field; field = field->next) { 684 if (!field->name) { 685 autofill_struct(ctx, type_dealias(field->type), fields); 686 continue; 687 } 688 size_t i = 0; 689 bool skip = false; 690 for (; fields[i]; ++i) { 691 if (!strcmp(field->name, fields[i]->field->name)) { 692 skip = true; 693 break; 694 } 695 } 696 if (!skip) { 697 fields[i] = xcalloc(1, sizeof(struct struct_constant)); 698 fields[i]->field = field; 699 fields[i]->value = xcalloc(1, sizeof(struct expression)); 700 fields[i]->value->type = EXPR_CONSTANT; 701 fields[i]->value->result = field->type; 702 constant_default(ctx, fields[i]->value); 703 } 704 } 705 } 706 707 enum eval_result 708 eval_struct(struct context *ctx, struct expression *in, struct expression *out) 709 { 710 assert(in->type == EXPR_STRUCT); 711 assert(type_dealias(in->result)->storage != STORAGE_UNION); // TODO 712 const struct type *type = type_dealias(in->result); 713 714 size_t n = count_struct_fields(type); 715 assert(n > 0); 716 717 size_t i = 0; 718 struct struct_constant **fields = 719 xcalloc(n, sizeof(struct struct_constant *)); 720 for (const struct expr_struct_field *field_in = in->_struct.fields; 721 field_in; field_in = field_in->next, ++i) { 722 const struct struct_field *field = 723 type_get_field(type, field_in->field->name); 724 fields[i] = xcalloc(1, sizeof(struct struct_constant)); 725 fields[i]->field = field; 726 fields[i]->value = xcalloc(1, sizeof(struct expression)); 727 728 enum eval_result r = eval_expr(ctx, 729 field_in->value, fields[i]->value); 730 if (r != EVAL_OK) { 731 return r; 732 } 733 } 734 assert(in->_struct.autofill || i == n); 735 736 if (in->_struct.autofill) { 737 autofill_struct(ctx, type, fields); 738 } 739 740 qsort(fields, n, sizeof(struct struct_constant *), field_compar); 741 742 for (size_t i = 0; i < n - 1; ++i) { 743 fields[i]->next = fields[i + 1]; 744 } 745 746 out->constant._struct = fields[0]; 747 free(fields); 748 return EVAL_OK; 749 } 750 751 static enum eval_result 752 eval_tuple(struct context *ctx, struct expression *in, struct expression *out) 753 { 754 assert(in->type == EXPR_TUPLE); 755 const struct type *type = type_dealias(in->result); 756 757 struct tuple_constant *out_tuple_start, *out_tuple; 758 out_tuple_start = out_tuple = xcalloc(1, sizeof(struct tuple_constant)); 759 const struct expression_tuple *in_tuple = &in->tuple; 760 for (const struct type_tuple *field_type = &type->tuple; field_type; 761 field_type = field_type->next) { 762 out_tuple->value = xcalloc(1, sizeof(struct expression)); 763 enum eval_result r = 764 eval_expr(ctx, in_tuple->value, out_tuple->value); 765 if (r != EVAL_OK) { 766 return r; 767 } 768 out_tuple->field = field_type; 769 if (in_tuple->next) { 770 in_tuple = in_tuple->next; 771 out_tuple->next = 772 xcalloc(1, sizeof(struct tuple_constant)); 773 out_tuple = out_tuple->next; 774 } 775 } 776 777 out->constant.tuple = out_tuple_start; 778 return EVAL_OK; 779 } 780 781 782 static enum eval_result 783 eval_unarithm(struct context *ctx, struct expression *in, struct expression *out) 784 { 785 if (in->unarithm.op == UN_ADDRESS) { 786 assert(in->unarithm.operand->type == EXPR_ACCESS); 787 // TODO other access types 788 assert(in->unarithm.operand->access.type == ACCESS_IDENTIFIER); 789 if (in->unarithm.operand->access.object->otype != O_DECL) { 790 return EVAL_INVALID; 791 } 792 out->constant.object = in->unarithm.operand->access.object; 793 out->constant.ival = 0; 794 return EVAL_OK; 795 } 796 797 struct expression lvalue = {0}; 798 enum eval_result r = eval_expr(ctx, in->unarithm.operand, &lvalue); 799 if (r != EVAL_OK) { 800 return r; 801 } 802 803 switch (in->unarithm.op) { 804 case UN_ADDRESS: 805 assert(0); // handled above 806 case UN_BNOT: 807 out->constant.uval = ~lvalue.constant.uval; 808 break; 809 case UN_DEREF: 810 assert(0); // TODO 811 case UN_LNOT: 812 out->constant.bval = !lvalue.constant.bval; 813 break; 814 case UN_MINUS: 815 if (type_is_float(out->result)) { 816 out->constant.fval = -lvalue.constant.fval; 817 } else { 818 out->constant.ival = -lvalue.constant.ival; 819 } 820 break; 821 case UN_PLUS: 822 out->constant = lvalue.constant; 823 break; 824 } 825 826 return EVAL_OK; 827 } 828 829 enum eval_result 830 eval_expr(struct context *ctx, struct expression *in, struct expression *out) 831 { 832 out->result = in->result; 833 out->type = EXPR_CONSTANT; 834 835 switch (in->type) { 836 case EXPR_ACCESS: 837 return eval_access(ctx, in, out); 838 case EXPR_BINARITHM: 839 return eval_binarithm(ctx, in, out); 840 case EXPR_CAST: 841 return eval_cast(ctx, in, out); 842 case EXPR_CONSTANT: 843 return eval_const(ctx, in, out); 844 case EXPR_MEASURE: 845 return eval_measurement(ctx, in, out); 846 case EXPR_STRUCT: 847 return eval_struct(ctx, in, out); 848 case EXPR_SLICE: 849 assert(0); // TODO 850 case EXPR_TUPLE: 851 return eval_tuple(ctx, in, out); 852 case EXPR_UNARITHM: 853 return eval_unarithm(ctx, in, out); 854 case EXPR_ALLOC: 855 case EXPR_APPEND: 856 case EXPR_ASSERT: 857 case EXPR_ASSIGN: 858 case EXPR_BINDING: 859 case EXPR_BREAK: 860 case EXPR_CALL: 861 case EXPR_COMPOUND: 862 case EXPR_CONTINUE: 863 case EXPR_DEFER: 864 case EXPR_DELETE: 865 case EXPR_FOR: 866 case EXPR_FREE: 867 case EXPR_IF: 868 case EXPR_INSERT: 869 case EXPR_MATCH: 870 case EXPR_PROPAGATE: 871 case EXPR_RETURN: 872 case EXPR_SWITCH: 873 case EXPR_VAARG: 874 case EXPR_VAEND: 875 case EXPR_VASTART: 876 case EXPR_YIELD: 877 // Excluded from translation-compatible subset 878 return EVAL_INVALID; 879 } 880 assert(0); // Unreachable 881 }