Fix -P output.

This commit is contained in:
Christoffer Lerno
2025-01-09 20:45:42 +01:00
parent b941f93416
commit 713199d7be

View File

@@ -162,734 +162,31 @@ void print_type(FILE *file, TypeInfo *type)
void print_var_expr(FILE *file, Expr *expr);
void print_var_expr_unary(FILE *file, ExprUnary *expr, bool is_post)
{
if (is_post) print_var_expr(file, expr->expr);
switch (expr->operator)
{
case UNARYOP_ERROR:
UNREACHABLE
case UNARYOP_DEREF:
fputs("*", file);
break;
case UNARYOP_ADDR:
fputs("&", file);
break;
case UNARYOP_NEG:
fputs("-", file);
break;
case UNARYOP_PLUS:
fputs("+", file);
break;
case UNARYOP_BITNEG:
fputs("~", file);
break;
case UNARYOP_NOT:
fputs("!", file);
break;
case UNARYOP_INC:
fputs("++", file);
break;
case UNARYOP_DEC:
fputs("--", file);
break;
case UNARYOP_TADDR:
fputs("&&", file);
break;
}
if (!is_post) print_var_expr(file, expr->expr);
}
void print_var_expr_range(FILE *file, Range *r)
{
if (r->is_len)
{
if (r->start_from_end) fputs("^", file);
PRINTF("%d", r->start_index);
fputs(" : ", file);
if (r->end_from_end) fputs("^", file);
PRINTF("%d", r->len_index);
}
else
{
switch (r->range_type)
{
case RANGE_DYNAMIC:
if (r->start_from_end) fputs("^", file);
print_var_expr(file, exprptr(r->start));
fputs("..", file);
if (r->end) print_var_expr(file, exprptr(r->end));
break;
case RANGE_CONST_END:
fputs("TODO: RANGE_CONST_END", file);
break;
case RANGE_CONST_LEN:
fputs("TODO: RANGE_CONST_LEN", file);
break;
case RANGE_CONST_RANGE:
fputs("TODO: RANGE_CONST_RANGE", file);
break;
}
}
}
void print_var_expr(FILE *file, Expr *expr)
{
if (!expr)
{
fputs("NULL EXPR", file);
return;
}
switch ( expr->expr_kind)
{
case EXPR_ADDR_CONVERSION:
print_var_expr(file, expr->inner_expr);
break;
case EXPR_MAKE_SLICE:
fputs("TODO: MAKE_SLICE", file);
break;
case EXPR_MAKE_ANY:
fputs("TODO: MAKE_ANY", file);
break;
case EXPR_DISCARD:
fputs("(void)", file);
print_var_expr(file, expr->access_expr.parent);
break;
case EXPR_BITASSIGN:
case EXPR_BITACCESS:
case EXPR_ACCESS:
print_var_expr(file, expr->access_expr.parent);
fputs(".", file);
print_var_expr(file, expr->access_expr.child);
break;
case EXPR_RVALUE:
case EXPR_RECAST:
fputs("(", file);
print_var_expr(file, expr->access_expr.parent);
fputs(")", file);
break;
case EXPR_ANYFAULT_TO_FAULT:
fputs("TODO: ANYFAULT TO FAULT", file);
break;
case EXPR_VECTOR_FROM_ARRAY:
fputs("TODO: VEC FROM ARRAY", file);
break;
case EXPR_SLICE_LEN:
print_var_expr(file, expr->access_expr.parent);
fputs(".len", file);
break;
case EXPR_FLOAT_TO_INT:
case EXPR_INT_TO_FLOAT:
case EXPR_INT_TO_PTR:
case EXPR_PTR_TO_INT:
case EXPR_ENUM_FROM_ORD:
case EXPR_VECTOR_TO_ARRAY:
case EXPR_SLICE_TO_VEC_ARRAY:
case EXPR_SCALAR_TO_VECTOR:
case EXPR_EXT_TRUNC:
fputs("TODO: MISSING IMPL", file);
break;
case EXPR_PTR_ACCESS:
print_var_expr(file, expr->access_expr.parent);
fputs(".ptr", file);
break;
case EXPR_INT_TO_BOOL:
fputs(expr->int_to_bool_expr.negate ? "!" : "!!", file);
print_var_expr(file, expr->inner_expr);
break;
case EXPR_BINARY:
print_var_expr(file, exprptr(expr->binary_expr.left));
switch (expr->binary_expr.operator)
{
case BINARYOP_ERROR:
UNREACHABLE
case BINARYOP_MULT:
fputs(" * ", file);
break;
case BINARYOP_SUB:
fputs(" - ", file);
break;
case BINARYOP_ADD:
fputs(" + ", file);
break;
case BINARYOP_DIV:
fputs(" / ", file);
break;
case BINARYOP_MOD:
fputs(" % ", file);
break;
case BINARYOP_SHR:
fputs(" >> ", file);
break;
case BINARYOP_SHL:
fputs(" << ", file);
break;
case BINARYOP_BIT_OR:
fputs(" | ", file);
break;
case BINARYOP_BIT_XOR:
fputs(" ^ ", file);
break;
case BINARYOP_BIT_AND:
fputs(" & ", file);
break;
case BINARYOP_AND:
case BINARYOP_CT_AND:
fputs(" && ", file);
break;
case BINARYOP_OR:
case BINARYOP_CT_OR:
fputs(" || ", file);
break;
case BINARYOP_ELSE:
fputs(" ?? ", file);
break;
case BINARYOP_CT_CONCAT:
fputs(" +++ ", file);
break;
case BINARYOP_GT:
fputs(" > ", file);
break;
case BINARYOP_GE:
fputs(" >= ", file);
break;
case BINARYOP_LT:
fputs(" < ", file);
break;
case BINARYOP_LE:
fputs(" <= ", file);
break;
case BINARYOP_NE:
fputs(" != ", file);
break;
case BINARYOP_EQ:
fputs(" == ", file);
break;
case BINARYOP_ASSIGN:
fputs(" = ", file);
break;
case BINARYOP_ADD_ASSIGN:
fputs(" += ", file);
break;
case BINARYOP_BIT_AND_ASSIGN:
fputs(" &= ", file);
break;
case BINARYOP_BIT_OR_ASSIGN:
fputs(" |= ", file);
break;
case BINARYOP_BIT_XOR_ASSIGN:
fputs(" ^= ", file);
break;
case BINARYOP_DIV_ASSIGN:
fputs(" /= ", file);
break;
case BINARYOP_MOD_ASSIGN:
fputs(" %= ", file);
break;
case BINARYOP_MULT_ASSIGN:
fputs(" *= ", file);
break;
case BINARYOP_SHR_ASSIGN:
fputs(" >>= ", file);
break;
case BINARYOP_SHL_ASSIGN:
fputs(" <<= ", file);
break;
case BINARYOP_SUB_ASSIGN:
fputs(" -= ", file);
break;
case BINARYOP_VEC_GT:
case BINARYOP_VEC_GE:
case BINARYOP_VEC_LT:
case BINARYOP_VEC_LE:
case BINARYOP_VEC_NE:
case BINARYOP_VEC_EQ:
fputs("/*VEC COMPARE TODO*/", file);
break;
}
print_var_expr(file, exprptr(expr->binary_expr.right));
break;
case EXPR_TYPECALL:
case EXPR_CALL:
{
if (!expr->call_expr.is_pointer_call) print_var_expr(file, exprptr(expr->call_expr.function));
fputs("(", file);
FOREACH_IDX(i, Expr *, e, expr->call_expr.arguments)
{
print_var_expr(file, e);
if (i != vec_size(expr->call_expr.arguments) - 1) fputs(", ", file);
}
fputs(")", file);
}
break;
case EXPR_CAST:
UNREACHABLE
case EXPR_BUILTIN:
case EXPR_COMPILER_CONST:
PRINTF("$$%s", expr->builtin_expr.ident);
break;
case EXPR_COMPOUND_LITERAL:
print_type(file, expr->expr_compound_literal.type_info);
print_var_expr(file, expr->expr_compound_literal.initializer);
break;
case EXPR_CONST:
switch (expr->const_expr.const_kind)
{
case CONST_FLOAT:
PRINTF("%f", expr->const_expr.fxx.f);
break;
case CONST_INTEGER:
fputs(i128_to_string(expr->const_expr.ixx.i, 10, true, false), file);
break;
case CONST_BOOL:
fputs(expr->const_expr.b ? "true" : "false", file);
break;
case CONST_ENUM:
PRINTF("%u", expr->const_expr.enum_err_val->enum_constant.ordinal);
break;
case CONST_ERR:
fputs("TODO: CONST_ERR", file);
break;
case CONST_BYTES:
{
fputs("x\\\"", file);
ArraySize len = expr->const_expr.bytes.len;
if (len == 0)
{
fputs("\\\"", file);
break;
}
const unsigned char *ptr = (unsigned char *)expr->const_expr.bytes.ptr;
char *res = malloc_string((size_t)(len * 3 + 1));
char *c = res;
for (ArraySize i = 0; i < len; ++i)
{
unsigned char curr = ptr[i];
char h = (curr & 0xF0) >> 4;
*(c++) = h > 0x09 ? h - 10 + 'A' : h + '0';
char l = curr & 0x0F;
*(c++) = l > 0x09 ? l - 10 + 'A' : l + '0';
}
*(c - 1) = '\\';
*c = 0;
fputs(res, file);
fputs("\"", file);
}
break;
case CONST_STRING:
{
fputs("\\\"", file);
ArraySize len = expr->const_expr.bytes.len;
const char *ptr = expr->const_expr.bytes.ptr;
char *res = malloc_string((size_t)(len * 6 + 1));
char *c = res;
for (ArraySize i = 0; i < len; ++i)
{
char curr = ptr[i];
if (curr <= 0x1F && curr >= 0x00)
{
*(c++) = '\\';
*(c++) = 'u';
*(c++) = '0';
*(c++) = '0';
*(c++) = ((curr & 0x10) >> 4) + '0';
char b = curr & 0x0F;
*(c++) = b > 0x09 ? b - 10 + 'A' : b + '0';
}
else
{
if (curr == '\\' || curr == '\"') *(c++) = '\\';
*(c++) = curr;
}
}
*c = 0;
fputs(res, file);
fputs("\\\"", file);
}
break;
case CONST_POINTER:
PRINTF("%llu", (unsigned long long) expr->const_expr.ptr);
break;
case CONST_TYPEID:
fputs(expr->const_expr.typeid->name, file);
break;
case CONST_SLICE:
fputs("TODO: CONST_SLICE", file);
break;
case CONST_INITIALIZER:
fputs("TODO: CONST_INITIALIZER", file);
break;
case CONST_UNTYPED_LIST:
fputs("{", file);
{
FOREACH_IDX(i, Expr *, e, expr->const_expr.untyped_list)
{
print_var_expr(file, e);
if (i != vec_size(expr->const_expr.untyped_list) - 1) fputs(", ", file);
}
}
fputs("}", file);
break;
case CONST_REF:
fputs("TODO: CONST_REF", file);
break;
case CONST_MEMBER:
fputs("TODO: CONST_MEMBER", file);
break;
}
break;
case EXPR_CT_AND_OR:
{
if (expr->ct_and_or_expr.is_and)
{
fputs("$and(", file);
}
else
{
fputs("$or(", file);
}
FOREACH_IDX(i, Expr *, e, expr->ct_and_or_expr.args)
{
print_var_expr(file, e);
if (i != vec_size(expr->ct_and_or_expr.args) - 1) fputs(", ", file);
}
fputs(")", file);
}
break;
case EXPR_CT_ARG:
fputs("$", file);
print_var_expr(file, exprptr(expr->ct_arg_expr.arg));
break;
case EXPR_CT_CALL:
switch (expr->ct_call_expr.token_type)
{
case TOKEN_CT_ALIGNOF: // $alignof
fputs("$alignof(", file);
break;
case TOKEN_CT_APPEND: // $append
fputs("$append(", file);
break;
case TOKEN_CT_ASSERT: // $assert
fputs("$assert(", file);
break;
case TOKEN_CT_ECHO: // $echo
fputs("$echo(", file);
break;
case TOKEN_CT_EMBED: // $embed
fputs("$embed(", file);
break;
case TOKEN_CT_EVALTYPE: // $evaltype
fputs("$evaltype(", file);
break;
case TOKEN_CT_ERROR: // $error
fputs("$error(", file);
break;
case TOKEN_CT_EXEC: // $exec
fputs("$exec(", file);
break;
case TOKEN_CT_EXTNAMEOF: // $extnameof
fputs("$extnameof(", file);
break;
case TOKEN_CT_FEATURE: // $feature
fputs("$feature(", file);
break;
case TOKEN_CT_NAMEOF: // $nameof
fputs("$nameof(", file);
break;
case TOKEN_CT_OFFSETOF: // $offsetof
fputs("$offsetof(", file);
break;
case TOKEN_CT_QNAMEOF: // $qnameof
fputs("$qnameof(", file);
break;
case TOKEN_CT_SIZEOF: // $sizeof
fputs("$sizeof(", file);
break;
case TOKEN_CT_STRINGIFY: // $stringify
fputs("$stringify(", file);
break;
case TOKEN_CT_TYPEFROM: // $typefrom
fputs("$typefrom(", file);
break;
case TOKEN_CT_TYPEOF: // $typeof
fputs("$typeof(", file);
break;
case TOKEN_CT_VACOUNT: // $vacount
fputs("$vacount(", file);
break;
case TOKEN_CT_VATYPE: // $vatype
fputs("$vatype(", file);
break;
case TOKEN_CT_VACONST: // $vaconst,
fputs("$vaconst(", file);
break;
case TOKEN_CT_VAREF: // $varef,
fputs("$varef(", file);
break;
case TOKEN_CT_VAARG: // $vaarg,
fputs("$vaarg(", file);
break;
case TOKEN_CT_VAEXPR: // $vaexpr,
fputs("$vaexpr(", file);
break;
default:
UNREACHABLE
}
print_var_expr(file, expr->ct_call_expr.main_var);
fputs(")", file);
break;
case EXPR_CT_CASTABLE:
fputs("$assignable(", file);
print_var_expr(file, exprptr(expr->castable_expr.expr));
fputs(", ", file);
print_type(file, type_infoptr(expr->castable_expr.type));
fputs(")", file);
break;
case EXPR_CT_APPEND:
case EXPR_CT_CONCAT:
{
FOREACH_IDX(i, Expr *, e, expr->ct_concat)
{
print_var_expr(file, e);
if (i != vec_size(expr->ct_concat) - 1) fputs(" +++ ", file);
}
}
break;
case EXPR_CT_DEFINED:
fputs("$defined(", file);
{
FOREACH_IDX(i, Expr *, e, expr->expression_list)
{
print_var_expr(file, e);
if (i != vec_size(expr->ct_concat) - 1) fputs(", ", file);
}
}
fputs(")", file);
break;
case EXPR_CT_EVAL:
fputs("$eval(", file);
print_var_expr(file, expr->inner_expr);
fputs(")", file);
break;
case EXPR_CT_IDENT:
fputs(expr->ct_ident_expr.identifier, file);
break;
case EXPR_CT_IS_CONST:
fputs("$is_const(", file);
print_var_expr(file, expr->inner_expr);
fputs(")", file);
break;
case EXPR_DECL:
fputs("TODO: EXPR_DECL", file);
break;
case EXPR_DESIGNATOR:
{
FOREACH(DesignatorElement *, d, expr->designator_expr.path)
{
switch (d->kind)
{
case DESIGNATOR_FIELD:
fputs(".", file);
print_var_expr(file, d->field_expr);
break;
case DESIGNATOR_ARRAY:
case DESIGNATOR_RANGE:
fputs("[", file);
if (d->index_expr) print_var_expr(file, d->index_expr);
if (d->index_end_expr)
{
fputs("..", file);
print_var_expr(file, d->index_end_expr);
}
fputs("]", file);
break;
}
}
fputs(" = ", file);
print_var_expr(file, expr->designator_expr.value);
}
break;
case EXPR_EMBED:
fputs("$embed(", file);
print_var_expr(file, expr->embed_expr.filename);
if (expr->embed_expr.len)
{
fputs(", ", file);
print_var_expr(file, expr->embed_expr.len);
}
break;
case EXPR_EXPRESSION_LIST:
{
FOREACH_IDX(i, Expr *, e, expr->expression_list)
{
print_var_expr(file, e);
if (i != vec_size(expr->ct_concat) - 1) fputs(", ", file);
}
}
break;
case EXPR_EXPR_BLOCK:
fputs("TODO: EXPR_EXPR_BLOCK", file);
break;
case EXPR_FORCE_UNWRAP:
print_var_expr(file, expr->inner_expr);
fputs("!!", file);
break;
case EXPR_GENERIC_IDENT:
print_var_expr(file, exprptr(expr->generic_ident_expr.parent));
fputs("(<", file);
{
FOREACH_IDX(i, Expr *, e, expr->generic_ident_expr.parmeters)
{
print_var_expr(file, e);
if (i != vec_size(expr->call_expr.arguments) - 1) fputs(", ", file);
}
}
fputs(">)", file);
break;
case EXPR_HASH_IDENT:
PRINTF("#%s", expr->hash_ident_expr.identifier);
break;
case EXPR_IDENTIFIER:
if (expr->identifier_expr.path)
{
if (expr->identifier_expr.path->module)
{
PRINTF("%s::", expr->identifier_expr.path->module);
}
}
if (expr->identifier_expr.ident)
{
fputs(expr->identifier_expr.ident, file);
}
break;
case EXPR_DESIGNATED_INITIALIZER_LIST:
case EXPR_INITIALIZER_LIST:
{
fputs("{ ", file);
FOREACH_IDX(i, Expr *, e, expr->initializer_list)
{
print_var_expr(file, e);
if (i != vec_size(expr->initializer_list) - 1) fputs(", ", file);
}
fputs(" }", file);
}
break;
case EXPR_LAMBDA:
fputs("TODO: EXPR_LAMBDA", file);
break;
case EXPR_MACRO_BLOCK:
fputs("TODO: EXPR_MACRO_BLOCK", file);
break;
case EXPR_MACRO_BODY_EXPANSION:
fputs("TODO: EXPR_MACRO_BODY_EXPANSION", file);
break;
case EXPR_MEMBER_GET:
fputs("TODO: EXPR_MEMBER_GET", file);
break;
case EXPR_NAMED_ARGUMENT:
PRINTF("%s: ", expr->named_argument_expr.name);
print_var_expr(file, expr->named_argument_expr.value);
break;
case EXPR_OPERATOR_CHARS:
fputs("TODO: EXPR_OPERATOR_CHARS", file);
break;
case EXPR_OPTIONAL:
print_var_expr(file, expr->inner_expr);
fputs("?", file);
break;
case EXPR_OTHER_CONTEXT:
fputs("TODO: EXPR_OTHER_CONTEXT", file);
break;
case EXPR_POINTER_OFFSET:
fputs("TODO: EXPR_POINTER_OFFSET", file);
break;
case EXPR_POST_UNARY:
print_var_expr_unary(file, &expr->unary_expr, true);
break;
case EXPR_RETHROW:
print_var_expr(file, expr->rethrow_expr.inner);
fputs("!", file);
break;
case EXPR_SLICE:
{
print_var_expr(file, exprptr(expr->slice_expr.expr));
fputs("[", file);
print_var_expr_range(file, &expr->slice_expr.range);
fputs("]", file);
}
break;
case EXPR_SLICE_ASSIGN:
fputs("TODO: EXPR_SLICE_ASSIGN", file);
break;
case EXPR_SLICE_COPY:
fputs("TODO: EXPR_SLICE_COPY", file);
break;
case EXPR_SPLAT:
fputs("TODO: EXPR_SPLAT", file);
break;
case EXPR_STRINGIFY:
fputs("$stringify(", file);
print_var_expr(file, expr->inner_expr);
fputs(")", file);
break;
case EXPR_SUBSCRIPT:
fputs("TODO: EXPR_SUBSCRIPT", file);
break;
case EXPR_SUBSCRIPT_ADDR:
fputs("TODO: EXPR_SUBSCRIPT_ADDR", file);
break;
case EXPR_SUBSCRIPT_ASSIGN:
UNREACHABLE
case EXPR_SWIZZLE:
fputs("TODO: EXPR_SWIZZLE", file);
break;
case EXPR_TERNARY:
{
print_var_expr(file, exprptr(expr->ternary_expr.cond));
fputs(" ? ", file);
Expr *then = exprptr(expr->ternary_expr.then_expr);
if (then) print_var_expr(file, then);
fputs(" : ", file);
print_var_expr(file, exprptr(expr->ternary_expr.else_expr));
}
break;
case EXPR_TYPEID:
print_type(file, expr->typeid_expr);
break;
case EXPR_TYPEID_INFO:
print_var_expr(file, exprptr(expr->typeid_info_expr.parent));
break;
case EXPR_TYPEINFO:
print_type(file, expr->type_expr);
break;
case EXPR_UNARY:
print_var_expr_unary(file, &expr->unary_expr, false);
break;
case EXPR_VASPLAT:
fputs("$vasplat[", file);
print_var_expr_range(file, &expr->vasplat_expr);
fputs("]", file);
break;
case EXPR_NOP:
case EXPR_ASM:
case EXPR_COND:
case EXPR_RETVAL:
// if not in doc lexing "mode", this is unreachable
case EXPR_POISONED:
case EXPR_TEST_HOOK:
case EXPR_ANYSWITCH:
case EXPR_TRY_UNWRAP:
case EXPR_LAST_FAULT:
case EXPR_MACRO_BODY:
// nested inside EXPR_CALL, avoid macro substitution
case EXPR_DEFAULT_ARG:
case EXPR_CATCH_UNWRAP:
case EXPR_BENCHMARK_HOOK:
case EXPR_BUILTIN_ACCESS:
case EXPR_TRY_UNWRAP_CHAIN:
UNREACHABLE
}
scratch_buffer_clear();
span_to_scratch(expr->span);
const char *str = scratch_buffer_to_string();
while (*str != 0)
{
char c = *str;
switch (c)
{
case '\r':
break;
case '\n':
fputs("\\n", file);
break;
case '\"':
fputs("\\\"", file);
break;
default:
fputc(c, file);
break;
}
++str;
}
}
static inline void emit_type_data(FILE *file, Module *module, Decl *type)