harec

[hare] Hare compiler, written in C11 for POSIX OSs
Log | Files | Refs | README | LICENSE

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 }