mirror of
https://github.com/ziglang/zig.git
synced 2025-12-06 06:13:07 +00:00
progress toward compile time constant expression evaluation
This commit is contained in:
parent
3c55162826
commit
a11d0aaf62
@ -233,6 +233,30 @@ static TypeTableEntry *get_array_type(CodeGen *g, ImportTableEntry *import,
|
||||
}
|
||||
}
|
||||
|
||||
static TypeTableEntry *eval_const_expr(CodeGen *g, BlockContext *context,
|
||||
AstNode *node, AstNodeNumberLiteral *out_number_literal)
|
||||
{
|
||||
switch (node->type) {
|
||||
case NodeTypeNumberLiteral:
|
||||
*out_number_literal = node->data.number_literal;
|
||||
return node->codegen_node->expr_node.type_entry;
|
||||
case NodeTypeBinOpExpr:
|
||||
zig_panic("TODO eval_const_expr bin op expr");
|
||||
break;
|
||||
case NodeTypeSymbol:
|
||||
{
|
||||
VariableTableEntry *var = find_variable(context, &node->data.symbol);
|
||||
assert(var);
|
||||
AstNode *decl_node = var->decl_node;
|
||||
AstNode *expr_node = decl_node->data.variable_declaration.expr;
|
||||
BlockContext *next_context = expr_node->codegen_node->expr_node.block_context;
|
||||
return eval_const_expr(g, next_context, expr_node, out_number_literal);
|
||||
}
|
||||
default:
|
||||
return g->builtin_types.entry_invalid;
|
||||
}
|
||||
}
|
||||
|
||||
static TypeTableEntry *resolve_type(CodeGen *g, AstNode *node, ImportTableEntry *import, BlockContext *context) {
|
||||
assert(node->type == NodeTypeType);
|
||||
alloc_codegen_node(node);
|
||||
@ -275,14 +299,27 @@ static TypeTableEntry *resolve_type(CodeGen *g, AstNode *node, ImportTableEntry
|
||||
}
|
||||
|
||||
AstNode *size_node = node->data.type.array_size;
|
||||
if (size_node->type == NodeTypeNumberLiteral &&
|
||||
is_num_lit_unsigned(size_node->data.number_literal.kind))
|
||||
{
|
||||
type_node->entry = get_array_type(g, import, child_type,
|
||||
size_node->data.number_literal.data.x_uint);
|
||||
TypeTableEntry *size_type = analyze_expression(g, import, context,
|
||||
g->builtin_types.entry_usize, size_node);
|
||||
if (size_type->id == TypeTableEntryIdInvalid) {
|
||||
type_node->entry = g->builtin_types.entry_invalid;
|
||||
return type_node->entry;
|
||||
}
|
||||
|
||||
AstNodeNumberLiteral number_literal;
|
||||
TypeTableEntry *resolved_type = eval_const_expr(g, context, size_node, &number_literal);
|
||||
|
||||
if (resolved_type->id == TypeTableEntryIdInt) {
|
||||
if (resolved_type->data.integral.is_signed) {
|
||||
add_node_error(g, size_node,
|
||||
buf_create_from_str("array size must be unsigned integer"));
|
||||
type_node->entry = g->builtin_types.entry_invalid;
|
||||
} else {
|
||||
type_node->entry = get_array_type(g, import, child_type, number_literal.data.x_uint);
|
||||
}
|
||||
} else {
|
||||
add_node_error(g, size_node,
|
||||
buf_create_from_str("array size must be literal unsigned integer"));
|
||||
buf_create_from_str("unable to resolve constant expression"));
|
||||
type_node->entry = g->builtin_types.entry_invalid;
|
||||
}
|
||||
return type_node->entry;
|
||||
|
||||
@ -1696,6 +1696,10 @@ static const NumLit num_lit_kinds[] = {
|
||||
NumLitU16,
|
||||
NumLitU32,
|
||||
NumLitU64,
|
||||
NumLitI8,
|
||||
NumLitI16,
|
||||
NumLitI32,
|
||||
NumLitI64,
|
||||
};
|
||||
|
||||
static void define_builtin_types(CodeGen *g) {
|
||||
|
||||
@ -2750,6 +2750,14 @@ const char *num_lit_str(NumLit num_lit) {
|
||||
return "u32";
|
||||
case NumLitU64:
|
||||
return "u64";
|
||||
case NumLitI8:
|
||||
return "i8";
|
||||
case NumLitI16:
|
||||
return "i16";
|
||||
case NumLitI32:
|
||||
return "i32";
|
||||
case NumLitI64:
|
||||
return "i64";
|
||||
case NumLitCount:
|
||||
zig_unreachable();
|
||||
}
|
||||
@ -2761,6 +2769,10 @@ bool is_num_lit_unsigned(NumLit num_lit) {
|
||||
case NumLitF32:
|
||||
case NumLitF64:
|
||||
case NumLitF128:
|
||||
case NumLitI8:
|
||||
case NumLitI16:
|
||||
case NumLitI32:
|
||||
case NumLitI64:
|
||||
return false;
|
||||
case NumLitU8:
|
||||
case NumLitU16:
|
||||
@ -2783,6 +2795,10 @@ bool is_num_lit_float(NumLit num_lit) {
|
||||
case NumLitU16:
|
||||
case NumLitU32:
|
||||
case NumLitU64:
|
||||
case NumLitI8:
|
||||
case NumLitI16:
|
||||
case NumLitI32:
|
||||
case NumLitI64:
|
||||
return false;
|
||||
case NumLitCount:
|
||||
zig_unreachable();
|
||||
@ -2793,13 +2809,17 @@ bool is_num_lit_float(NumLit num_lit) {
|
||||
uint64_t num_lit_bit_count(NumLit num_lit) {
|
||||
switch (num_lit) {
|
||||
case NumLitU8:
|
||||
case NumLitI8:
|
||||
return 8;
|
||||
case NumLitU16:
|
||||
case NumLitI16:
|
||||
return 16;
|
||||
case NumLitU32:
|
||||
case NumLitI32:
|
||||
case NumLitF32:
|
||||
return 32;
|
||||
case NumLitU64:
|
||||
case NumLitI64:
|
||||
case NumLitF64:
|
||||
return 64;
|
||||
case NumLitF128:
|
||||
|
||||
@ -309,6 +309,10 @@ enum NumLit {
|
||||
NumLitU16,
|
||||
NumLitU32,
|
||||
NumLitU64,
|
||||
NumLitI8,
|
||||
NumLitI16,
|
||||
NumLitI32,
|
||||
NumLitI64,
|
||||
|
||||
NumLitCount
|
||||
};
|
||||
@ -322,6 +326,7 @@ struct AstNodeNumberLiteral {
|
||||
|
||||
union {
|
||||
uint64_t x_uint;
|
||||
int64_t x_int;
|
||||
double x_float;
|
||||
} data;
|
||||
};
|
||||
|
||||
@ -777,6 +777,19 @@ pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {
|
||||
return 0;
|
||||
}
|
||||
)SOURCE", "OK\n");
|
||||
|
||||
add_simple_case("constant expressions", R"SOURCE(
|
||||
use "std.zig";
|
||||
|
||||
const ARRAY_SIZE : u8 = 20;
|
||||
|
||||
pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {
|
||||
var array : [u8; ARRAY_SIZE];
|
||||
print_u64(#sizeof(#typeof(array)));
|
||||
print_str("\n");
|
||||
return 0;
|
||||
}
|
||||
)SOURCE", "20\n");
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user