progress toward compile time constant expression evaluation

This commit is contained in:
Andrew Kelley 2016-01-04 23:37:17 -07:00
parent 3c55162826
commit a11d0aaf62
5 changed files with 85 additions and 6 deletions

View File

@ -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;

View File

@ -1696,6 +1696,10 @@ static const NumLit num_lit_kinds[] = {
NumLitU16,
NumLitU32,
NumLitU64,
NumLitI8,
NumLitI16,
NumLitI32,
NumLitI64,
};
static void define_builtin_types(CodeGen *g) {

View File

@ -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:

View File

@ -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;
};

View File

@ -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");
}
////////////////////////////////////////////////////////////////////////////////////