eval: ability to eval more things
parent
fa605485ea
commit
aa89fd3b3e
|
@ -65,7 +65,6 @@ struct ConstExprValue {
|
|||
bool ok; // true if constant expression evalution worked
|
||||
bool depends_on_compile_var;
|
||||
bool undef;
|
||||
bool deep_const;
|
||||
|
||||
union {
|
||||
BigNum x_bignum;
|
||||
|
@ -961,6 +960,7 @@ struct TypeTableEntry {
|
|||
LLVMZigDIType *di_type;
|
||||
|
||||
bool zero_bits;
|
||||
bool deep_const;
|
||||
|
||||
union {
|
||||
TypeTableEntryPointer pointer;
|
||||
|
|
135
src/analyze.cpp
135
src/analyze.cpp
|
@ -207,6 +207,7 @@ TypeTableEntry *get_smallest_unsigned_int_type(CodeGen *g, uint64_t x) {
|
|||
static TypeTableEntry *get_generic_fn_type(CodeGen *g, AstNode *decl_node) {
|
||||
TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdGenericFn);
|
||||
buf_init_from_str(&entry->name, "(generic function)");
|
||||
entry->deep_const = true;
|
||||
entry->zero_bits = true;
|
||||
entry->data.generic_fn.decl_node = decl_node;
|
||||
return entry;
|
||||
|
@ -220,6 +221,8 @@ TypeTableEntry *get_pointer_to_type(CodeGen *g, TypeTableEntry *child_type, bool
|
|||
} else {
|
||||
TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdPointer);
|
||||
|
||||
entry->deep_const = is_const && child_type->deep_const;
|
||||
|
||||
const char *const_str = is_const ? "const " : "";
|
||||
buf_resize(&entry->name, 0);
|
||||
buf_appendf(&entry->name, "&%s%s", const_str, buf_ptr(&child_type->name));
|
||||
|
@ -261,6 +264,8 @@ TypeTableEntry *get_maybe_type(CodeGen *g, TypeTableEntry *child_type) {
|
|||
assert(child_type->type_ref);
|
||||
assert(child_type->di_type);
|
||||
|
||||
entry->deep_const = child_type->deep_const;
|
||||
|
||||
buf_resize(&entry->name, 0);
|
||||
buf_appendf(&entry->name, "?%s", buf_ptr(&child_type->name));
|
||||
|
||||
|
@ -344,6 +349,8 @@ static TypeTableEntry *get_error_type(CodeGen *g, TypeTableEntry *child_type) {
|
|||
|
||||
entry->data.error.child_type = child_type;
|
||||
|
||||
entry->deep_const = child_type->deep_const;
|
||||
|
||||
if (!type_has_bits(child_type)) {
|
||||
entry->type_ref = g->err_tag_type->type_ref;
|
||||
entry->di_type = g->err_tag_type->di_type;
|
||||
|
@ -415,6 +422,7 @@ TypeTableEntry *get_array_type(CodeGen *g, TypeTableEntry *child_type, uint64_t
|
|||
TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdArray);
|
||||
entry->type_ref = LLVMArrayType(child_type->type_ref, array_size);
|
||||
entry->zero_bits = (array_size == 0) || child_type->zero_bits;
|
||||
entry->deep_const = child_type->deep_const;
|
||||
|
||||
buf_resize(&entry->name, 0);
|
||||
buf_appendf(&entry->name, "[%" PRIu64 "]%s", array_size, buf_ptr(&child_type->name));
|
||||
|
@ -465,6 +473,8 @@ TypeTableEntry *get_slice_type(CodeGen *g, TypeTableEntry *child_type, bool is_c
|
|||
TypeTableEntry *var_peer = get_slice_type(g, child_type, false);
|
||||
TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdStruct);
|
||||
|
||||
entry->deep_const = child_type->deep_const;
|
||||
|
||||
buf_resize(&entry->name, 0);
|
||||
buf_appendf(&entry->name, "[]const %s", buf_ptr(&child_type->name));
|
||||
|
||||
|
@ -550,6 +560,7 @@ TypeTableEntry *get_typedecl_type(CodeGen *g, const char *name, TypeTableEntry *
|
|||
|
||||
buf_init_from_str(&entry->name, name);
|
||||
|
||||
entry->deep_const = child_type->deep_const;
|
||||
entry->type_ref = child_type->type_ref;
|
||||
entry->di_type = child_type->di_type;
|
||||
entry->zero_bits = child_type->zero_bits;
|
||||
|
@ -573,6 +584,7 @@ TypeTableEntry *get_fn_type(CodeGen *g, FnTypeId *fn_type_id) {
|
|||
}
|
||||
|
||||
TypeTableEntry *fn_type = new_type_table_entry(TypeTableEntryIdFn);
|
||||
fn_type->deep_const = true;
|
||||
fn_type->data.fn.fn_type_id = *fn_type_id;
|
||||
if (fn_type_id->param_info == &fn_type_id->prealloc_param_info[0]) {
|
||||
fn_type->data.fn.fn_type_id.param_info = &fn_type->data.fn.fn_type_id.prealloc_param_info[0];
|
||||
|
@ -1038,6 +1050,8 @@ static void resolve_enum_type(CodeGen *g, ImportTableEntry *import, TypeTableEnt
|
|||
|
||||
assert(enum_type->di_type);
|
||||
|
||||
enum_type->deep_const = true;
|
||||
|
||||
uint32_t field_count = decl_node->data.struct_decl.fields.length;
|
||||
|
||||
enum_type->data.enumeration.field_count = field_count;
|
||||
|
@ -1065,6 +1079,10 @@ static void resolve_enum_type(CodeGen *g, ImportTableEntry *import, TypeTableEnt
|
|||
type_enum_field->type_entry = field_type;
|
||||
type_enum_field->value = i;
|
||||
|
||||
if (!field_type->deep_const) {
|
||||
enum_type->deep_const = false;
|
||||
}
|
||||
|
||||
|
||||
di_enumerators[i] = LLVMZigCreateDebugEnumerator(g->dbuilder, buf_ptr(type_enum_field->name), i);
|
||||
|
||||
|
@ -1225,6 +1243,8 @@ static void resolve_struct_type(CodeGen *g, ImportTableEntry *import, TypeTableE
|
|||
|
||||
assert(struct_type->di_type);
|
||||
|
||||
struct_type->deep_const = true;
|
||||
|
||||
int field_count = decl_node->data.struct_decl.fields.length;
|
||||
|
||||
struct_type->data.structure.src_field_count = field_count;
|
||||
|
@ -1248,6 +1268,10 @@ static void resolve_struct_type(CodeGen *g, ImportTableEntry *import, TypeTableE
|
|||
type_struct_field->src_index = i;
|
||||
type_struct_field->gen_index = -1;
|
||||
|
||||
if (!field_type->deep_const) {
|
||||
struct_type->deep_const = false;
|
||||
}
|
||||
|
||||
if (field_type->id == TypeTableEntryIdStruct) {
|
||||
resolve_struct_type(g, import, field_type);
|
||||
} else if (field_type->id == TypeTableEntryIdEnum) {
|
||||
|
@ -2486,7 +2510,6 @@ static TypeTableEntry *analyze_array_access_expr(CodeGen *g, ImportTableEntry *i
|
|||
static TypeTableEntry *resolve_expr_const_val_as_void(CodeGen *g, AstNode *node) {
|
||||
Expr *expr = get_resolved_expr(node);
|
||||
expr->const_val.ok = true;
|
||||
expr->const_val.deep_const = true;
|
||||
return g->builtin_types.entry_void;
|
||||
}
|
||||
|
||||
|
@ -2494,7 +2517,6 @@ static TypeTableEntry *resolve_expr_const_val_as_type(CodeGen *g, AstNode *node,
|
|||
Expr *expr = get_resolved_expr(node);
|
||||
expr->const_val.ok = true;
|
||||
expr->const_val.data.x_type = type;
|
||||
expr->const_val.deep_const = true;
|
||||
return g->builtin_types.entry_type;
|
||||
}
|
||||
|
||||
|
@ -2509,7 +2531,6 @@ static TypeTableEntry *resolve_expr_const_val_as_fn(CodeGen *g, AstNode *node, F
|
|||
Expr *expr = get_resolved_expr(node);
|
||||
expr->const_val.ok = true;
|
||||
expr->const_val.data.x_fn = fn;
|
||||
expr->const_val.deep_const = true;
|
||||
return fn->type_entry;
|
||||
}
|
||||
|
||||
|
@ -2519,7 +2540,6 @@ static TypeTableEntry *resolve_expr_const_val_as_generic_fn(CodeGen *g, AstNode
|
|||
Expr *expr = get_resolved_expr(node);
|
||||
expr->const_val.ok = true;
|
||||
expr->const_val.data.x_type = type_entry;
|
||||
expr->const_val.deep_const = true;
|
||||
return type_entry;
|
||||
}
|
||||
|
||||
|
@ -2527,7 +2547,6 @@ static TypeTableEntry *resolve_expr_const_val_as_err(CodeGen *g, AstNode *node,
|
|||
Expr *expr = get_resolved_expr(node);
|
||||
expr->const_val.ok = true;
|
||||
expr->const_val.data.x_err.err = err;
|
||||
expr->const_val.deep_const = true;
|
||||
return g->builtin_types.entry_pure_error;
|
||||
}
|
||||
|
||||
|
@ -2538,7 +2557,6 @@ static TypeTableEntry *resolve_expr_const_val_as_bool(CodeGen *g, AstNode *node,
|
|||
expr->const_val.ok = true;
|
||||
expr->const_val.depends_on_compile_var = depends_on_compile_var;
|
||||
expr->const_val.data.x_bool = value;
|
||||
expr->const_val.deep_const = true;
|
||||
return g->builtin_types.entry_bool;
|
||||
}
|
||||
|
||||
|
@ -2546,7 +2564,6 @@ static TypeTableEntry *resolve_expr_const_val_as_null(CodeGen *g, AstNode *node,
|
|||
Expr *expr = get_resolved_expr(node);
|
||||
expr->const_val.ok = true;
|
||||
expr->const_val.data.x_maybe = nullptr;
|
||||
expr->const_val.deep_const = true;
|
||||
return type;
|
||||
}
|
||||
|
||||
|
@ -2557,14 +2574,12 @@ static TypeTableEntry *resolve_expr_const_val_as_non_null(CodeGen *g, AstNode *n
|
|||
Expr *expr = get_resolved_expr(node);
|
||||
expr->const_val.ok = true;
|
||||
expr->const_val.data.x_maybe = other_val;
|
||||
expr->const_val.deep_const = other_val->deep_const;
|
||||
return type;
|
||||
}
|
||||
|
||||
static TypeTableEntry *resolve_expr_const_val_as_c_string_lit(CodeGen *g, AstNode *node, Buf *str) {
|
||||
Expr *expr = get_resolved_expr(node);
|
||||
expr->const_val.ok = true;
|
||||
expr->const_val.deep_const = true;
|
||||
|
||||
int len_with_null = buf_len(str) + 1;
|
||||
expr->const_val.data.x_ptr.ptr = allocate<ConstExprValue*>(len_with_null);
|
||||
|
@ -2574,14 +2589,12 @@ static TypeTableEntry *resolve_expr_const_val_as_c_string_lit(CodeGen *g, AstNod
|
|||
for (int i = 0; i < buf_len(str); i += 1) {
|
||||
ConstExprValue *this_char = &all_chars[i];
|
||||
this_char->ok = true;
|
||||
this_char->deep_const = true;
|
||||
bignum_init_unsigned(&this_char->data.x_bignum, buf_ptr(str)[i]);
|
||||
expr->const_val.data.x_ptr.ptr[i] = this_char;
|
||||
}
|
||||
|
||||
ConstExprValue *null_char = &all_chars[len_with_null - 1];
|
||||
null_char->ok = true;
|
||||
null_char->deep_const = true;
|
||||
bignum_init_unsigned(&null_char->data.x_bignum, 0);
|
||||
expr->const_val.data.x_ptr.ptr[len_with_null - 1] = null_char;
|
||||
|
||||
|
@ -2591,14 +2604,12 @@ static TypeTableEntry *resolve_expr_const_val_as_c_string_lit(CodeGen *g, AstNod
|
|||
static TypeTableEntry *resolve_expr_const_val_as_string_lit(CodeGen *g, AstNode *node, Buf *str) {
|
||||
Expr *expr = get_resolved_expr(node);
|
||||
expr->const_val.ok = true;
|
||||
expr->const_val.deep_const = true;
|
||||
expr->const_val.data.x_array.fields = allocate<ConstExprValue*>(buf_len(str));
|
||||
|
||||
ConstExprValue *all_chars = allocate<ConstExprValue>(buf_len(str));
|
||||
for (int i = 0; i < buf_len(str); i += 1) {
|
||||
ConstExprValue *this_char = &all_chars[i];
|
||||
this_char->ok = true;
|
||||
this_char->deep_const = true;
|
||||
bignum_init_unsigned(&this_char->data.x_bignum, buf_ptr(str)[i]);
|
||||
expr->const_val.data.x_array.fields[i] = this_char;
|
||||
}
|
||||
|
@ -2611,7 +2622,6 @@ static TypeTableEntry *resolve_expr_const_val_as_unsigned_num_lit(CodeGen *g, As
|
|||
{
|
||||
Expr *expr = get_resolved_expr(node);
|
||||
expr->const_val.ok = true;
|
||||
expr->const_val.deep_const = true;
|
||||
|
||||
bignum_init_unsigned(&expr->const_val.data.x_bignum, x);
|
||||
|
||||
|
@ -2623,7 +2633,6 @@ static TypeTableEntry *resolve_expr_const_val_as_float_num_lit(CodeGen *g, AstNo
|
|||
{
|
||||
Expr *expr = get_resolved_expr(node);
|
||||
expr->const_val.ok = true;
|
||||
expr->const_val.deep_const = true;
|
||||
|
||||
bignum_init_float(&expr->const_val.data.x_bignum, x);
|
||||
|
||||
|
@ -2639,7 +2648,6 @@ static TypeTableEntry *resolve_expr_const_val_as_bignum_op(CodeGen *g, AstNode *
|
|||
ConstExprValue *op2_val = &get_resolved_expr(op2)->const_val;
|
||||
|
||||
const_val->ok = true;
|
||||
const_val->deep_const = true;
|
||||
|
||||
if (bignum_fn(&const_val->data.x_bignum, &op1_val->data.x_bignum, &op2_val->data.x_bignum)) {
|
||||
add_node_error(g, node,
|
||||
|
@ -2713,12 +2721,7 @@ static bool var_is_pure(VariableTableEntry *var, TypeTableEntry *var_type, Block
|
|||
// variable was declared in the current function, so it's OK.
|
||||
return true;
|
||||
}
|
||||
if (!var->is_const) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ConstExprValue *const_val = &get_resolved_expr(var->val_node)->const_val;
|
||||
return const_val->deep_const;
|
||||
return var->is_const && var->type->deep_const;
|
||||
}
|
||||
|
||||
static TypeTableEntry *analyze_symbol_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
|
||||
|
@ -3714,17 +3717,6 @@ static TypeTableEntry *analyze_if_var_expr(CodeGen *g, ImportTableEntry *import,
|
|||
node, then_node, else_node, cond_is_const, cond_bool_val);
|
||||
}
|
||||
|
||||
static bool int_type_depends_on_compile_var(CodeGen *g, TypeTableEntry *int_type) {
|
||||
assert(int_type->id == TypeTableEntryIdInt);
|
||||
|
||||
for (int i = 0; i < CIntTypeCount; i += 1) {
|
||||
if (int_type == g->builtin_types.entry_c_int[i]) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static TypeTableEntry *analyze_min_max_value(CodeGen *g, ImportTableEntry *import, BlockContext *context,
|
||||
AstNode *node, const char *err_format, bool is_max)
|
||||
{
|
||||
|
@ -3733,67 +3725,15 @@ static TypeTableEntry *analyze_min_max_value(CodeGen *g, ImportTableEntry *impor
|
|||
|
||||
AstNode *type_node = node->data.fn_call_expr.params.at(0);
|
||||
TypeTableEntry *type_entry = analyze_type_expr(g, import, context, type_node);
|
||||
|
||||
if (type_entry->id == TypeTableEntryIdInvalid) {
|
||||
return g->builtin_types.entry_invalid;
|
||||
} else if (type_entry->id == TypeTableEntryIdInt) {
|
||||
ConstExprValue *const_val = &get_resolved_expr(node)->const_val;
|
||||
const_val->ok = true;
|
||||
const_val->depends_on_compile_var = int_type_depends_on_compile_var(g, type_entry);
|
||||
if (is_max) {
|
||||
if (type_entry->data.integral.is_signed) {
|
||||
int64_t val;
|
||||
if (type_entry->data.integral.bit_count == 64) {
|
||||
val = INT64_MAX;
|
||||
} else if (type_entry->data.integral.bit_count == 32) {
|
||||
val = INT32_MAX;
|
||||
} else if (type_entry->data.integral.bit_count == 16) {
|
||||
val = INT16_MAX;
|
||||
} else if (type_entry->data.integral.bit_count == 8) {
|
||||
val = INT8_MAX;
|
||||
} else {
|
||||
zig_unreachable();
|
||||
}
|
||||
bignum_init_signed(&const_val->data.x_bignum, val);
|
||||
} else {
|
||||
uint64_t val;
|
||||
if (type_entry->data.integral.bit_count == 64) {
|
||||
val = UINT64_MAX;
|
||||
} else if (type_entry->data.integral.bit_count == 32) {
|
||||
val = UINT32_MAX;
|
||||
} else if (type_entry->data.integral.bit_count == 16) {
|
||||
val = UINT16_MAX;
|
||||
} else if (type_entry->data.integral.bit_count == 8) {
|
||||
val = UINT8_MAX;
|
||||
} else {
|
||||
zig_unreachable();
|
||||
}
|
||||
bignum_init_unsigned(&const_val->data.x_bignum, val);
|
||||
}
|
||||
} else {
|
||||
if (type_entry->data.integral.is_signed) {
|
||||
int64_t val;
|
||||
if (type_entry->data.integral.bit_count == 64) {
|
||||
val = INT64_MIN;
|
||||
} else if (type_entry->data.integral.bit_count == 32) {
|
||||
val = INT32_MIN;
|
||||
} else if (type_entry->data.integral.bit_count == 16) {
|
||||
val = INT16_MIN;
|
||||
} else if (type_entry->data.integral.bit_count == 8) {
|
||||
val = INT8_MIN;
|
||||
} else {
|
||||
zig_unreachable();
|
||||
}
|
||||
bignum_init_signed(&const_val->data.x_bignum, val);
|
||||
} else {
|
||||
bignum_init_unsigned(&const_val->data.x_bignum, 0);
|
||||
}
|
||||
}
|
||||
} else if (type_entry->id == TypeTableEntryIdInt ||
|
||||
type_entry->id == TypeTableEntryIdFloat ||
|
||||
type_entry->id == TypeTableEntryIdBool)
|
||||
{
|
||||
eval_min_max_value(g, type_entry, &get_resolved_expr(node)->const_val, is_max);
|
||||
return type_entry;
|
||||
} else if (type_entry->id == TypeTableEntryIdFloat) {
|
||||
zig_panic("TODO analyze_min_max_value float");
|
||||
return type_entry;
|
||||
} else if (type_entry->id == TypeTableEntryIdBool) {
|
||||
return resolve_expr_const_val_as_bool(g, node, is_max, false);
|
||||
} else {
|
||||
add_node_error(g, node,
|
||||
buf_sprintf(err_format, buf_ptr(&type_entry->name)));
|
||||
|
@ -3810,7 +3750,8 @@ static TypeTableEntry *resolve_cast(CodeGen *g, BlockContext *context, AstNode *
|
|||
TypeTableEntry *other_type = get_resolved_expr(expr_node)->type_entry;
|
||||
ConstExprValue *const_val = &get_resolved_expr(node)->const_val;
|
||||
if (other_val->ok) {
|
||||
eval_const_expr_implicit_cast(node->data.fn_call_expr.cast_op, other_val, other_type, const_val);
|
||||
eval_const_expr_implicit_cast(node->data.fn_call_expr.cast_op, other_val, other_type,
|
||||
const_val, wanted_type);
|
||||
}
|
||||
|
||||
if (need_alloca) {
|
||||
|
@ -4238,8 +4179,6 @@ static TypeTableEntry *analyze_builtin_fn_call_expr(CodeGen *g, ImportTableEntry
|
|||
}
|
||||
case BuiltinFnIdMemcpy:
|
||||
{
|
||||
mark_impure_fn(context);
|
||||
|
||||
AstNode *dest_node = node->data.fn_call_expr.params.at(0);
|
||||
AstNode *src_node = node->data.fn_call_expr.params.at(1);
|
||||
AstNode *len_node = node->data.fn_call_expr.params.at(2);
|
||||
|
@ -4278,8 +4217,6 @@ static TypeTableEntry *analyze_builtin_fn_call_expr(CodeGen *g, ImportTableEntry
|
|||
}
|
||||
case BuiltinFnIdMemset:
|
||||
{
|
||||
mark_impure_fn(context);
|
||||
|
||||
AstNode *dest_node = node->data.fn_call_expr.params.at(0);
|
||||
AstNode *char_node = node->data.fn_call_expr.params.at(1);
|
||||
AstNode *len_node = node->data.fn_call_expr.params.at(2);
|
||||
|
@ -4601,6 +4538,8 @@ static TypeTableEntry *analyze_fn_call_ptr(CodeGen *g, ImportTableEntry *import,
|
|||
// calling an impure fn is impure
|
||||
mark_impure_fn(context);
|
||||
}
|
||||
} else {
|
||||
mark_impure_fn(context);
|
||||
}
|
||||
|
||||
if (handle_is_ptr(return_type)) {
|
||||
|
@ -5602,6 +5541,10 @@ static void analyze_fn_body(CodeGen *g, FnTableEntry *fn_table_entry) {
|
|||
param_decl_node->data.param_decl.variable = var;
|
||||
|
||||
var->gen_arg_index = fn_type->data.fn.gen_param_info[i].gen_index;
|
||||
|
||||
if (!type->deep_const) {
|
||||
fn_table_entry->is_pure = false;
|
||||
}
|
||||
}
|
||||
|
||||
TypeTableEntry *expected_type = fn_type->data.fn.fn_type_id.return_type;
|
||||
|
|
|
@ -71,6 +71,11 @@ bool bignum_fits_in_bits(BigNum *bn, int bit_count, bool is_signed) {
|
|||
}
|
||||
}
|
||||
|
||||
void bignum_truncate(BigNum *bn, int bit_count) {
|
||||
assert(bn->kind == BigNumKindInt);
|
||||
bn->data.x_uint &= (1LL << bit_count) - 1;
|
||||
}
|
||||
|
||||
uint64_t bignum_to_twos_complement(BigNum *bn) {
|
||||
assert(bn->kind == BigNumKindInt);
|
||||
|
||||
|
|
|
@ -47,6 +47,8 @@ void bignum_negate(BigNum *dest, BigNum *op);
|
|||
void bignum_cast_to_float(BigNum *dest, BigNum *op);
|
||||
void bignum_cast_to_int(BigNum *dest, BigNum *op);
|
||||
|
||||
void bignum_truncate(BigNum *dest, int bit_count);
|
||||
|
||||
// returns the result of the comparison
|
||||
bool bignum_cmp_eq(BigNum *op1, BigNum *op2);
|
||||
bool bignum_cmp_neq(BigNum *op1, BigNum *op2);
|
||||
|
|
|
@ -3463,23 +3463,27 @@ static void define_builtin_types(CodeGen *g) {
|
|||
TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdNamespace);
|
||||
buf_init_from_str(&entry->name, "(namespace)");
|
||||
entry->zero_bits = true;
|
||||
entry->deep_const = true;
|
||||
g->builtin_types.entry_namespace = entry;
|
||||
}
|
||||
{
|
||||
TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdNumLitFloat);
|
||||
buf_init_from_str(&entry->name, "(float literal)");
|
||||
entry->zero_bits = true;
|
||||
entry->deep_const = true;
|
||||
g->builtin_types.entry_num_lit_float = entry;
|
||||
}
|
||||
{
|
||||
TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdNumLitInt);
|
||||
buf_init_from_str(&entry->name, "(integer literal)");
|
||||
entry->zero_bits = true;
|
||||
entry->deep_const = true;
|
||||
g->builtin_types.entry_num_lit_int = entry;
|
||||
}
|
||||
{
|
||||
TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdUndefLit);
|
||||
buf_init_from_str(&entry->name, "(undefined)");
|
||||
entry->deep_const = true;
|
||||
g->builtin_types.entry_undef = entry;
|
||||
}
|
||||
|
||||
|
@ -3489,6 +3493,7 @@ static void define_builtin_types(CodeGen *g) {
|
|||
for (;;) {
|
||||
TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdInt);
|
||||
entry->type_ref = LLVMIntType(size_in_bits);
|
||||
entry->deep_const = true;
|
||||
|
||||
const char u_or_i = is_signed ? 'i' : 'u';
|
||||
buf_resize(&entry->name, 0);
|
||||
|
@ -3534,6 +3539,7 @@ static void define_builtin_types(CodeGen *g) {
|
|||
|
||||
TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdInt);
|
||||
entry->type_ref = LLVMIntType(size_in_bits);
|
||||
entry->deep_const = true;
|
||||
|
||||
buf_init_from_str(&entry->name, info->name);
|
||||
|
||||
|
@ -3553,6 +3559,7 @@ static void define_builtin_types(CodeGen *g) {
|
|||
{
|
||||
TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdBool);
|
||||
entry->type_ref = LLVMInt1Type();
|
||||
entry->deep_const = true;
|
||||
buf_init_from_str(&entry->name, "bool");
|
||||
uint64_t debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, entry->type_ref);
|
||||
uint64_t debug_align_in_bits = 8*LLVMABISizeOfType(g->target_data_ref, entry->type_ref);
|
||||
|
@ -3565,6 +3572,7 @@ static void define_builtin_types(CodeGen *g) {
|
|||
}
|
||||
{
|
||||
TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdInt);
|
||||
entry->deep_const = true;
|
||||
entry->type_ref = LLVMIntType(g->pointer_size_bytes * 8);
|
||||
buf_init_from_str(&entry->name, "isize");
|
||||
entry->data.integral.is_signed = true;
|
||||
|
@ -3581,6 +3589,7 @@ static void define_builtin_types(CodeGen *g) {
|
|||
}
|
||||
{
|
||||
TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdInt);
|
||||
entry->deep_const = true;
|
||||
entry->type_ref = LLVMIntType(g->pointer_size_bytes * 8);
|
||||
buf_init_from_str(&entry->name, "usize");
|
||||
entry->data.integral.is_signed = false;
|
||||
|
@ -3597,6 +3606,7 @@ static void define_builtin_types(CodeGen *g) {
|
|||
}
|
||||
{
|
||||
TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdFloat);
|
||||
entry->deep_const = true;
|
||||
entry->type_ref = LLVMFloatType();
|
||||
buf_init_from_str(&entry->name, "f32");
|
||||
entry->data.floating.bit_count = 32;
|
||||
|
@ -3612,6 +3622,7 @@ static void define_builtin_types(CodeGen *g) {
|
|||
}
|
||||
{
|
||||
TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdFloat);
|
||||
entry->deep_const = true;
|
||||
entry->type_ref = LLVMDoubleType();
|
||||
buf_init_from_str(&entry->name, "f64");
|
||||
entry->data.floating.bit_count = 64;
|
||||
|
@ -3627,6 +3638,7 @@ static void define_builtin_types(CodeGen *g) {
|
|||
}
|
||||
{
|
||||
TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdFloat);
|
||||
entry->deep_const = true;
|
||||
entry->type_ref = LLVMX86FP80Type();
|
||||
buf_init_from_str(&entry->name, "c_long_double");
|
||||
entry->data.floating.bit_count = 80;
|
||||
|
@ -3642,6 +3654,7 @@ static void define_builtin_types(CodeGen *g) {
|
|||
}
|
||||
{
|
||||
TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdVoid);
|
||||
entry->deep_const = true;
|
||||
entry->type_ref = LLVMVoidType();
|
||||
entry->zero_bits = true;
|
||||
buf_init_from_str(&entry->name, "void");
|
||||
|
@ -3654,6 +3667,7 @@ static void define_builtin_types(CodeGen *g) {
|
|||
}
|
||||
{
|
||||
TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdUnreachable);
|
||||
entry->deep_const = true;
|
||||
entry->type_ref = LLVMVoidType();
|
||||
entry->zero_bits = true;
|
||||
buf_init_from_str(&entry->name, "unreachable");
|
||||
|
@ -3663,6 +3677,7 @@ static void define_builtin_types(CodeGen *g) {
|
|||
}
|
||||
{
|
||||
TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdMetaType);
|
||||
entry->deep_const = true;
|
||||
buf_init_from_str(&entry->name, "type");
|
||||
entry->zero_bits = true;
|
||||
g->builtin_types.entry_type = entry;
|
||||
|
@ -3685,6 +3700,7 @@ static void define_builtin_types(CodeGen *g) {
|
|||
|
||||
{
|
||||
TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdPureError);
|
||||
entry->deep_const = true;
|
||||
buf_init_from_str(&entry->name, "error");
|
||||
|
||||
// TODO allow overriding this type and keep track of max value and emit an
|
||||
|
@ -3700,6 +3716,7 @@ static void define_builtin_types(CodeGen *g) {
|
|||
|
||||
{
|
||||
TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdEnum);
|
||||
entry->deep_const = true;
|
||||
entry->zero_bits = true; // only allowed at compile time
|
||||
buf_init_from_str(&entry->name, "@OS");
|
||||
uint32_t field_count = target_os_count();
|
||||
|
@ -3725,6 +3742,7 @@ static void define_builtin_types(CodeGen *g) {
|
|||
|
||||
{
|
||||
TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdEnum);
|
||||
entry->deep_const = true;
|
||||
entry->zero_bits = true; // only allowed at compile time
|
||||
buf_init_from_str(&entry->name, "@Arch");
|
||||
uint32_t field_count = target_arch_count();
|
||||
|
@ -3756,6 +3774,7 @@ static void define_builtin_types(CodeGen *g) {
|
|||
|
||||
{
|
||||
TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdEnum);
|
||||
entry->deep_const = true;
|
||||
entry->zero_bits = true; // only allowed at compile time
|
||||
buf_init_from_str(&entry->name, "@Environ");
|
||||
uint32_t field_count = target_environ_count();
|
||||
|
|
284
src/eval.cpp
284
src/eval.cpp
|
@ -360,7 +360,7 @@ static bool eval_if_bool_expr(EvalFn *ef, AstNode *node, ConstExprValue *out_val
|
|||
|
||||
void eval_const_expr_implicit_cast(CastOp cast_op,
|
||||
ConstExprValue *other_val, TypeTableEntry *other_type,
|
||||
ConstExprValue *const_val)
|
||||
ConstExprValue *const_val, TypeTableEntry *new_type)
|
||||
{
|
||||
const_val->depends_on_compile_var = other_val->depends_on_compile_var;
|
||||
const_val->undef = other_val->undef;
|
||||
|
@ -371,9 +371,30 @@ void eval_const_expr_implicit_cast(CastOp cast_op,
|
|||
zig_unreachable();
|
||||
case CastOpNoop:
|
||||
case CastOpWidenOrShorten:
|
||||
case CastOpPointerReinterpret:
|
||||
*const_val = *other_val;
|
||||
break;
|
||||
case CastOpPointerReinterpret:
|
||||
{
|
||||
TypeTableEntry *other_child_type = other_type->data.pointer.child_type;
|
||||
TypeTableEntry *new_child_type = new_type->data.pointer.child_type;
|
||||
|
||||
if ((other_child_type->id == TypeTableEntryIdInt ||
|
||||
other_child_type->id == TypeTableEntryIdFloat) &&
|
||||
(new_child_type->id == TypeTableEntryIdInt ||
|
||||
new_child_type->id == TypeTableEntryIdFloat))
|
||||
{
|
||||
ConstExprValue **ptr_val = allocate<ConstExprValue*>(1);
|
||||
*ptr_val = other_val->data.x_ptr.ptr[0];
|
||||
const_val->data.x_ptr.ptr = ptr_val;
|
||||
const_val->data.x_ptr.len = 1;
|
||||
const_val->ok = true;
|
||||
const_val->undef = other_val->undef;
|
||||
const_val->depends_on_compile_var = other_val->depends_on_compile_var;
|
||||
} else {
|
||||
zig_panic("TODO");
|
||||
}
|
||||
break;
|
||||
}
|
||||
case CastOpPtrToInt:
|
||||
case CastOpIntToPtr:
|
||||
// can't do it
|
||||
|
@ -435,20 +456,184 @@ void eval_const_expr_implicit_cast(CastOp cast_op,
|
|||
}
|
||||
}
|
||||
|
||||
static bool int_type_depends_on_compile_var(CodeGen *g, TypeTableEntry *int_type) {
|
||||
assert(int_type->id == TypeTableEntryIdInt);
|
||||
|
||||
for (int i = 0; i < CIntTypeCount; i += 1) {
|
||||
if (int_type == g->builtin_types.entry_c_int[i]) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void eval_min_max_value(CodeGen *g, TypeTableEntry *type_entry, ConstExprValue *const_val, bool is_max) {
|
||||
if (type_entry->id == TypeTableEntryIdInt) {
|
||||
const_val->ok = true;
|
||||
const_val->depends_on_compile_var = int_type_depends_on_compile_var(g, type_entry);
|
||||
if (is_max) {
|
||||
if (type_entry->data.integral.is_signed) {
|
||||
int64_t val;
|
||||
if (type_entry->data.integral.bit_count == 64) {
|
||||
val = INT64_MAX;
|
||||
} else if (type_entry->data.integral.bit_count == 32) {
|
||||
val = INT32_MAX;
|
||||
} else if (type_entry->data.integral.bit_count == 16) {
|
||||
val = INT16_MAX;
|
||||
} else if (type_entry->data.integral.bit_count == 8) {
|
||||
val = INT8_MAX;
|
||||
} else {
|
||||
zig_unreachable();
|
||||
}
|
||||
bignum_init_signed(&const_val->data.x_bignum, val);
|
||||
} else {
|
||||
uint64_t val;
|
||||
if (type_entry->data.integral.bit_count == 64) {
|
||||
val = UINT64_MAX;
|
||||
} else if (type_entry->data.integral.bit_count == 32) {
|
||||
val = UINT32_MAX;
|
||||
} else if (type_entry->data.integral.bit_count == 16) {
|
||||
val = UINT16_MAX;
|
||||
} else if (type_entry->data.integral.bit_count == 8) {
|
||||
val = UINT8_MAX;
|
||||
} else {
|
||||
zig_unreachable();
|
||||
}
|
||||
bignum_init_unsigned(&const_val->data.x_bignum, val);
|
||||
}
|
||||
} else {
|
||||
if (type_entry->data.integral.is_signed) {
|
||||
int64_t val;
|
||||
if (type_entry->data.integral.bit_count == 64) {
|
||||
val = INT64_MIN;
|
||||
} else if (type_entry->data.integral.bit_count == 32) {
|
||||
val = INT32_MIN;
|
||||
} else if (type_entry->data.integral.bit_count == 16) {
|
||||
val = INT16_MIN;
|
||||
} else if (type_entry->data.integral.bit_count == 8) {
|
||||
val = INT8_MIN;
|
||||
} else {
|
||||
zig_unreachable();
|
||||
}
|
||||
bignum_init_signed(&const_val->data.x_bignum, val);
|
||||
} else {
|
||||
bignum_init_unsigned(&const_val->data.x_bignum, 0);
|
||||
}
|
||||
}
|
||||
} else if (type_entry->id == TypeTableEntryIdFloat) {
|
||||
zig_panic("TODO analyze_min_max_value float");
|
||||
} else if (type_entry->id == TypeTableEntryIdBool) {
|
||||
const_val->ok = true;
|
||||
const_val->data.x_bool = is_max;
|
||||
} else {
|
||||
zig_unreachable();
|
||||
}
|
||||
}
|
||||
|
||||
static bool eval_min_max(EvalFn *ef, AstNode *node, ConstExprValue *out_val, bool is_max) {
|
||||
assert(node->type == NodeTypeFnCallExpr);
|
||||
AstNode *type_node = node->data.fn_call_expr.params.at(0);
|
||||
TypeTableEntry *type_entry = resolve_expr_type(type_node);
|
||||
eval_min_max_value(ef->root->codegen, type_entry, out_val, is_max);
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool eval_fn_with_overflow(EvalFn *ef, AstNode *node, ConstExprValue *out_val,
|
||||
bool (*bignum_fn)(BigNum *dest, BigNum *op1, BigNum *op2))
|
||||
{
|
||||
assert(node->type == NodeTypeFnCallExpr);
|
||||
|
||||
AstNode *type_node = node->data.fn_call_expr.params.at(0);
|
||||
TypeTableEntry *int_type = resolve_expr_type(type_node);
|
||||
assert(int_type->id == TypeTableEntryIdInt);
|
||||
|
||||
AstNode *op1_node = node->data.fn_call_expr.params.at(1);
|
||||
AstNode *op2_node = node->data.fn_call_expr.params.at(2);
|
||||
AstNode *result_node = node->data.fn_call_expr.params.at(3);
|
||||
|
||||
ConstExprValue op1_val = {0};
|
||||
if (eval_expr(ef, op1_node, &op1_val)) return true;
|
||||
|
||||
ConstExprValue op2_val = {0};
|
||||
if (eval_expr(ef, op2_node, &op2_val)) return true;
|
||||
|
||||
ConstExprValue result_ptr_val = {0};
|
||||
if (eval_expr(ef, result_node, &result_ptr_val)) return true;
|
||||
|
||||
ConstExprValue *result_val = result_ptr_val.data.x_ptr.ptr[0];
|
||||
|
||||
out_val->ok = true;
|
||||
bool overflow = bignum_fn(&result_val->data.x_bignum, &op1_val.data.x_bignum, &op2_val.data.x_bignum);
|
||||
|
||||
overflow = overflow || !bignum_fits_in_bits(&result_val->data.x_bignum,
|
||||
int_type->data.integral.bit_count, int_type->data.integral.is_signed);
|
||||
|
||||
out_val->data.x_bool = overflow;
|
||||
|
||||
if (overflow) {
|
||||
bignum_truncate(&result_val->data.x_bignum, int_type->data.integral.bit_count);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool eval_fn_call_builtin(EvalFn *ef, AstNode *node, ConstExprValue *out_val) {
|
||||
assert(node->type == NodeTypeFnCallExpr);
|
||||
|
||||
BuiltinFnEntry *builtin_fn = node->data.fn_call_expr.builtin_fn;
|
||||
switch (builtin_fn->id) {
|
||||
case BuiltinFnIdMaxValue:
|
||||
return eval_min_max(ef, node, out_val, true);
|
||||
case BuiltinFnIdMinValue:
|
||||
return eval_min_max(ef, node, out_val, false);
|
||||
case BuiltinFnIdMulWithOverflow:
|
||||
return eval_fn_with_overflow(ef, node, out_val, bignum_mul);
|
||||
case BuiltinFnIdAddWithOverflow:
|
||||
return eval_fn_with_overflow(ef, node, out_val, bignum_add);
|
||||
case BuiltinFnIdSubWithOverflow:
|
||||
return eval_fn_with_overflow(ef, node, out_val, bignum_sub);
|
||||
case BuiltinFnIdMemcpy:
|
||||
case BuiltinFnIdMemset:
|
||||
case BuiltinFnIdSizeof:
|
||||
case BuiltinFnIdAlignof:
|
||||
case BuiltinFnIdMemberCount:
|
||||
case BuiltinFnIdTypeof:
|
||||
case BuiltinFnIdCInclude:
|
||||
case BuiltinFnIdCDefine:
|
||||
case BuiltinFnIdCUndef:
|
||||
case BuiltinFnIdCompileVar:
|
||||
case BuiltinFnIdConstEval:
|
||||
case BuiltinFnIdCtz:
|
||||
case BuiltinFnIdClz:
|
||||
case BuiltinFnIdImport:
|
||||
case BuiltinFnIdCImport:
|
||||
case BuiltinFnIdErrName:
|
||||
zig_panic("TODO");
|
||||
case BuiltinFnIdBreakpoint:
|
||||
case BuiltinFnIdInvalid:
|
||||
zig_unreachable();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool eval_fn_call_expr(EvalFn *ef, AstNode *node, ConstExprValue *out_val) {
|
||||
assert(node->type == NodeTypeFnCallExpr);
|
||||
|
||||
AstNode *fn_ref_expr = node->data.fn_call_expr.fn_ref_expr;
|
||||
CastOp cast_op = node->data.fn_call_expr.cast_op;
|
||||
if (node->data.fn_call_expr.is_builtin) {
|
||||
zig_panic("TODO");
|
||||
return eval_fn_call_builtin(ef, node, out_val);
|
||||
} else if (cast_op != CastOpNoCast) {
|
||||
AstNode *expr_node = node->data.fn_call_expr.params.at(0);
|
||||
Expr *expr = get_resolved_expr(expr_node);
|
||||
eval_const_expr_implicit_cast(cast_op, &expr->const_val, expr->type_entry, out_val);
|
||||
TypeTableEntry *new_type = resolve_expr_type(fn_ref_expr);
|
||||
AstNode *param_node = node->data.fn_call_expr.params.at(0);
|
||||
TypeTableEntry *old_type = get_resolved_expr(param_node)->type_entry;
|
||||
ConstExprValue param_val = {0};
|
||||
if (eval_expr(ef, param_node, ¶m_val)) return true;
|
||||
eval_const_expr_implicit_cast(cast_op, ¶m_val, old_type, out_val, new_type);
|
||||
return false;
|
||||
}
|
||||
|
||||
AstNode *fn_ref_expr = node->data.fn_call_expr.fn_ref_expr;
|
||||
if (node->data.fn_call_expr.enum_type) {
|
||||
zig_panic("TODO");
|
||||
}
|
||||
|
@ -503,7 +688,12 @@ static bool eval_field_access_expr(EvalFn *ef, AstNode *node, ConstExprValue *ou
|
|||
zig_panic("TODO");
|
||||
}
|
||||
} else if (struct_type->id == TypeTableEntryIdMetaType) {
|
||||
zig_panic("TODO");
|
||||
TypeTableEntry *child_type = resolve_expr_type(struct_expr);
|
||||
if (child_type->id == TypeTableEntryIdPureError) {
|
||||
*out_val = get_resolved_expr(node)->const_val;
|
||||
} else {
|
||||
zig_panic("TODO");
|
||||
}
|
||||
} else if (struct_type->id == TypeTableEntryIdNamespace) {
|
||||
zig_panic("TODO");
|
||||
} else {
|
||||
|
@ -630,7 +820,6 @@ static bool eval_bool_literal_expr(EvalFn *ef, AstNode *node, ConstExprValue *ou
|
|||
assert(node->type == NodeTypeBoolLiteral);
|
||||
|
||||
out_val->ok = true;
|
||||
out_val->deep_const = true;
|
||||
out_val->data.x_bool = node->data.bool_literal.value;
|
||||
|
||||
return false;
|
||||
|
@ -640,20 +829,38 @@ static bool eval_prefix_op_expr(EvalFn *ef, AstNode *node, ConstExprValue *out_v
|
|||
assert(node->type == NodeTypePrefixOpExpr);
|
||||
|
||||
PrefixOp prefix_op = node->data.prefix_op_expr.prefix_op;
|
||||
AstNode *expr_node = node->data.prefix_op_expr.primary_expr;
|
||||
|
||||
ConstExprValue expr_val = {0};
|
||||
if (eval_expr(ef, node->data.prefix_op_expr.primary_expr, &expr_val)) return true;
|
||||
if (eval_expr(ef, expr_node, &expr_val)) return true;
|
||||
|
||||
TypeTableEntry *expr_type = get_resolved_expr(expr_node)->type_entry;
|
||||
|
||||
switch (prefix_op) {
|
||||
case PrefixOpBoolNot:
|
||||
*out_val = expr_val;
|
||||
out_val->data.x_bool = !out_val->data.x_bool;
|
||||
break;
|
||||
case PrefixOpBinNot:
|
||||
case PrefixOpNegation:
|
||||
case PrefixOpDereference:
|
||||
assert(expr_type->id == TypeTableEntryIdPointer);
|
||||
*out_val = *expr_val.data.x_ptr.ptr[0];
|
||||
break;
|
||||
case PrefixOpAddressOf:
|
||||
case PrefixOpConstAddressOf:
|
||||
case PrefixOpDereference:
|
||||
{
|
||||
ConstExprValue *child_val = allocate<ConstExprValue>(1);
|
||||
*child_val = expr_val;
|
||||
|
||||
ConstExprValue **ptr_val = allocate<ConstExprValue*>(1);
|
||||
*ptr_val = child_val;
|
||||
|
||||
out_val->data.x_ptr.ptr = ptr_val;
|
||||
out_val->data.x_ptr.len = 1;
|
||||
out_val->ok = true;
|
||||
break;
|
||||
}
|
||||
case PrefixOpBinNot:
|
||||
case PrefixOpNegation:
|
||||
case PrefixOpMaybe:
|
||||
case PrefixOpError:
|
||||
case PrefixOpUnwrapError:
|
||||
|
@ -666,6 +873,48 @@ static bool eval_prefix_op_expr(EvalFn *ef, AstNode *node, ConstExprValue *out_v
|
|||
return false;
|
||||
}
|
||||
|
||||
static bool eval_var_decl_expr(EvalFn *ef, AstNode *node, ConstExprValue *out_val) {
|
||||
assert(node->type == NodeTypeVariableDeclaration);
|
||||
|
||||
assert(node->data.variable_declaration.expr);
|
||||
|
||||
EvalScope *my_scope = ef->scope_stack.at(ef->scope_stack.length - 1);
|
||||
|
||||
my_scope->vars.add_one();
|
||||
EvalVar *var = &my_scope->vars.last();
|
||||
var->name = &node->data.variable_declaration.symbol;
|
||||
|
||||
if (eval_expr(ef, node->data.variable_declaration.expr, &var->value)) return true;
|
||||
|
||||
out_val->ok = true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool eval_number_literal_expr(EvalFn *ef, AstNode *node, ConstExprValue *out_val) {
|
||||
assert(node->type == NodeTypeNumberLiteral);
|
||||
assert(!node->data.number_literal.overflow);
|
||||
|
||||
out_val->ok = true;
|
||||
if (node->data.number_literal.kind == NumLitUInt) {
|
||||
bignum_init_unsigned(&out_val->data.x_bignum, node->data.number_literal.data.x_uint);
|
||||
} else if (node->data.number_literal.kind == NumLitFloat) {
|
||||
bignum_init_float(&out_val->data.x_bignum, node->data.number_literal.data.x_float);
|
||||
} else {
|
||||
zig_unreachable();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool eval_char_literal_expr(EvalFn *ef, AstNode *node, ConstExprValue *out_val) {
|
||||
assert(node->type == NodeTypeCharLiteral);
|
||||
|
||||
out_val->ok = true;
|
||||
bignum_init_unsigned(&out_val->data.x_bignum, node->data.char_literal.value);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool eval_expr(EvalFn *ef, AstNode *node, ConstExprValue *out) {
|
||||
if (ef->root->branches_used > ef->root->branch_quota) {
|
||||
|
@ -697,6 +946,12 @@ static bool eval_expr(EvalFn *ef, AstNode *node, ConstExprValue *out) {
|
|||
return eval_bool_literal_expr(ef, node, out);
|
||||
case NodeTypePrefixOpExpr:
|
||||
return eval_prefix_op_expr(ef, node, out);
|
||||
case NodeTypeVariableDeclaration:
|
||||
return eval_var_decl_expr(ef, node, out);
|
||||
case NodeTypeNumberLiteral:
|
||||
return eval_number_literal_expr(ef, node, out);
|
||||
case NodeTypeCharLiteral:
|
||||
return eval_char_literal_expr(ef, node, out);
|
||||
case NodeTypeRoot:
|
||||
case NodeTypeFnProto:
|
||||
case NodeTypeFnDef:
|
||||
|
@ -704,13 +959,10 @@ static bool eval_expr(EvalFn *ef, AstNode *node, ConstExprValue *out) {
|
|||
case NodeTypeParamDecl:
|
||||
case NodeTypeDirective:
|
||||
case NodeTypeDefer:
|
||||
case NodeTypeVariableDeclaration:
|
||||
case NodeTypeTypeDecl:
|
||||
case NodeTypeErrorValueDecl:
|
||||
case NodeTypeUnwrapErrorExpr:
|
||||
case NodeTypeNumberLiteral:
|
||||
case NodeTypeStringLiteral:
|
||||
case NodeTypeCharLiteral:
|
||||
case NodeTypeSliceExpr:
|
||||
case NodeTypeUse:
|
||||
case NodeTypeNullLiteral:
|
||||
|
|
|
@ -19,6 +19,8 @@ void eval_const_expr_bin_op(ConstExprValue *op1_val, TypeTableEntry *op1_type,
|
|||
|
||||
void eval_const_expr_implicit_cast(CastOp cast_op,
|
||||
ConstExprValue *other_val, TypeTableEntry *other_type,
|
||||
ConstExprValue *const_val);
|
||||
ConstExprValue *const_val, TypeTableEntry *new_type);
|
||||
|
||||
void eval_min_max_value(CodeGen *g, TypeTableEntry *type_entry, ConstExprValue *const_val, bool is_max);
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue