parent
57688dea36
commit
1d4c66b56b
125
src/analyze.cpp
125
src/analyze.cpp
|
@ -974,7 +974,6 @@ static void resolve_function_proto(CodeGen *g, AstNode *node, FnTableEntry *fn_t
|
||||||
} else {
|
} else {
|
||||||
symbol_name = buf_sprintf("_%s", buf_ptr(&fn_table_entry->symbol_name));
|
symbol_name = buf_sprintf("_%s", buf_ptr(&fn_table_entry->symbol_name));
|
||||||
}
|
}
|
||||||
// TODO mangle the name if it's a generic instance
|
|
||||||
|
|
||||||
fn_table_entry->fn_value = LLVMAddFunction(g->module, buf_ptr(symbol_name),
|
fn_table_entry->fn_value = LLVMAddFunction(g->module, buf_ptr(symbol_name),
|
||||||
fn_type->data.fn.raw_type_ref);
|
fn_type->data.fn.raw_type_ref);
|
||||||
|
@ -2828,6 +2827,60 @@ static bool eval_bool_bin_op_bool(bool a, BinOpType bin_op, bool b) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool const_values_equal(ConstExprValue *a, ConstExprValue *b, TypeTableEntry *type_entry) {
|
||||||
|
switch (type_entry->id) {
|
||||||
|
case TypeTableEntryIdEnum:
|
||||||
|
{
|
||||||
|
ConstEnumValue *enum1 = &a->data.x_enum;
|
||||||
|
ConstEnumValue *enum2 = &b->data.x_enum;
|
||||||
|
if (enum1->tag == enum2->tag) {
|
||||||
|
TypeEnumField *enum_field = &type_entry->data.enumeration.fields[enum1->tag];
|
||||||
|
if (type_has_bits(enum_field->type_entry)) {
|
||||||
|
zig_panic("TODO const expr analyze enum special value for equality");
|
||||||
|
} else {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
case TypeTableEntryIdMetaType:
|
||||||
|
return a->data.x_type == b->data.x_type;
|
||||||
|
case TypeTableEntryIdVoid:
|
||||||
|
return true;
|
||||||
|
case TypeTableEntryIdPureError:
|
||||||
|
return a->data.x_err.err == b->data.x_err.err;
|
||||||
|
case TypeTableEntryIdFn:
|
||||||
|
return a->data.x_fn == b->data.x_fn;
|
||||||
|
case TypeTableEntryIdBool:
|
||||||
|
return a->data.x_bool == b->data.x_bool;
|
||||||
|
case TypeTableEntryIdInt:
|
||||||
|
case TypeTableEntryIdFloat:
|
||||||
|
case TypeTableEntryIdNumLitFloat:
|
||||||
|
case TypeTableEntryIdNumLitInt:
|
||||||
|
return bignum_cmp_eq(&a->data.x_bignum, &b->data.x_bignum);
|
||||||
|
case TypeTableEntryIdPointer:
|
||||||
|
zig_panic("TODO");
|
||||||
|
case TypeTableEntryIdArray:
|
||||||
|
zig_panic("TODO");
|
||||||
|
case TypeTableEntryIdStruct:
|
||||||
|
zig_panic("TODO");
|
||||||
|
case TypeTableEntryIdUndefLit:
|
||||||
|
zig_panic("TODO");
|
||||||
|
case TypeTableEntryIdMaybe:
|
||||||
|
zig_panic("TODO");
|
||||||
|
case TypeTableEntryIdErrorUnion:
|
||||||
|
zig_panic("TODO");
|
||||||
|
case TypeTableEntryIdTypeDecl:
|
||||||
|
zig_panic("TODO");
|
||||||
|
case TypeTableEntryIdNamespace:
|
||||||
|
zig_panic("TODO");
|
||||||
|
case TypeTableEntryIdGenericFn:
|
||||||
|
case TypeTableEntryIdInvalid:
|
||||||
|
case TypeTableEntryIdUnreachable:
|
||||||
|
zig_unreachable();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static TypeTableEntry *analyze_bool_bin_op_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
|
static TypeTableEntry *analyze_bool_bin_op_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
|
||||||
AstNode *node)
|
AstNode *node)
|
||||||
{
|
{
|
||||||
|
@ -2887,48 +2940,15 @@ static TypeTableEntry *analyze_bool_bin_op_expr(CodeGen *g, ImportTableEntry *im
|
||||||
}
|
}
|
||||||
|
|
||||||
answer = bignum_cmp(&op1_val->data.x_bignum, &op2_val->data.x_bignum);
|
answer = bignum_cmp(&op1_val->data.x_bignum, &op2_val->data.x_bignum);
|
||||||
|
|
||||||
} else if (resolved_type->id == TypeTableEntryIdEnum) {
|
|
||||||
ConstEnumValue *enum1 = &op1_val->data.x_enum;
|
|
||||||
ConstEnumValue *enum2 = &op2_val->data.x_enum;
|
|
||||||
bool are_equal = false;
|
|
||||||
if (enum1->tag == enum2->tag) {
|
|
||||||
TypeEnumField *enum_field = &op1_type->data.enumeration.fields[enum1->tag];
|
|
||||||
if (type_has_bits(enum_field->type_entry)) {
|
|
||||||
zig_panic("TODO const expr analyze enum special value for equality");
|
|
||||||
} else {
|
|
||||||
are_equal = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (bin_op_type == BinOpTypeCmpEq) {
|
|
||||||
answer = are_equal;
|
|
||||||
} else if (bin_op_type == BinOpTypeCmpNotEq) {
|
|
||||||
answer = !are_equal;
|
|
||||||
} else {
|
|
||||||
zig_unreachable();
|
|
||||||
}
|
|
||||||
} else if (resolved_type->id == TypeTableEntryIdPureError) {
|
|
||||||
bool are_equal = op1_val->data.x_err.err == op2_val->data.x_err.err;
|
|
||||||
|
|
||||||
if (bin_op_type == BinOpTypeCmpEq) {
|
|
||||||
answer = are_equal;
|
|
||||||
} else if (bin_op_type == BinOpTypeCmpNotEq) {
|
|
||||||
answer = !are_equal;
|
|
||||||
} else {
|
|
||||||
zig_unreachable();
|
|
||||||
}
|
|
||||||
} else if (resolved_type->id == TypeTableEntryIdFn) {
|
|
||||||
bool are_equal = (op1_val->data.x_fn == op2_val->data.x_fn);
|
|
||||||
|
|
||||||
if (bin_op_type == BinOpTypeCmpEq) {
|
|
||||||
answer = are_equal;
|
|
||||||
} else if (bin_op_type == BinOpTypeCmpNotEq) {
|
|
||||||
answer = !are_equal;
|
|
||||||
} else {
|
|
||||||
zig_unreachable();
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
zig_unreachable();
|
bool are_equal = const_values_equal(op1_val, op2_val, resolved_type);
|
||||||
|
if (bin_op_type == BinOpTypeCmpEq) {
|
||||||
|
answer = are_equal;
|
||||||
|
} else if (bin_op_type == BinOpTypeCmpNotEq) {
|
||||||
|
answer = !are_equal;
|
||||||
|
} else {
|
||||||
|
zig_unreachable();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool depends_on_compile_var = op1_val->depends_on_compile_var || op2_val->depends_on_compile_var;
|
bool depends_on_compile_var = op1_val->depends_on_compile_var || op2_val->depends_on_compile_var;
|
||||||
|
@ -4682,7 +4702,6 @@ static TypeTableEntry *analyze_generic_fn_call(CodeGen *g, ImportTableEntry *imp
|
||||||
generic_param_value->node = *param_node;
|
generic_param_value->node = *param_node;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
auto entry = g->generic_table.maybe_get(generic_fn_type_id);
|
auto entry = g->generic_table.maybe_get(generic_fn_type_id);
|
||||||
if (entry) {
|
if (entry) {
|
||||||
AstNode *impl_decl_node = entry->value;
|
AstNode *impl_decl_node = entry->value;
|
||||||
|
@ -4693,9 +4712,10 @@ static TypeTableEntry *analyze_generic_fn_call(CodeGen *g, ImportTableEntry *imp
|
||||||
|
|
||||||
// make a type from the generic parameters supplied
|
// make a type from the generic parameters supplied
|
||||||
assert(decl_node->type == NodeTypeFnProto);
|
assert(decl_node->type == NodeTypeFnProto);
|
||||||
AstNode *impl_fn_def_node = ast_clone_subtree(decl_node->data.fn_proto.fn_def_node);
|
AstNode *impl_fn_def_node = ast_clone_subtree(decl_node->data.fn_proto.fn_def_node, &g->next_node_index);
|
||||||
AstNode *impl_decl_node = impl_fn_def_node->data.fn_def.fn_proto;
|
AstNode *impl_decl_node = impl_fn_def_node->data.fn_def.fn_proto;
|
||||||
impl_decl_node->data.fn_proto.fn_def_node = impl_fn_def_node;
|
|
||||||
|
|
||||||
|
|
||||||
preview_fn_proto_instance(g, import, impl_decl_node, child_context);
|
preview_fn_proto_instance(g, import, impl_decl_node, child_context);
|
||||||
|
|
||||||
|
@ -6233,7 +6253,20 @@ uint32_t generic_fn_type_id_hash(GenericFnTypeId *id) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool generic_fn_type_id_eql(GenericFnTypeId *a, GenericFnTypeId *b) {
|
bool generic_fn_type_id_eql(GenericFnTypeId *a, GenericFnTypeId *b) {
|
||||||
// TODO
|
if (a->decl_node != b->decl_node) return false;
|
||||||
|
assert(a->generic_param_count == b->generic_param_count);
|
||||||
|
for (int i = 0; i < a->generic_param_count; i += 1) {
|
||||||
|
GenericParamValue *a_val = &a->generic_params[i];
|
||||||
|
GenericParamValue *b_val = &b->generic_params[i];
|
||||||
|
assert(a_val->type == b_val->type);
|
||||||
|
ConstExprValue *a_const_val = &get_resolved_expr(a_val->node)->const_val;
|
||||||
|
ConstExprValue *b_const_val = &get_resolved_expr(b_val->node)->const_val;
|
||||||
|
assert(a_const_val->ok);
|
||||||
|
assert(b_const_val->ok);
|
||||||
|
if (!const_values_equal(a_const_val, b_const_val, a_val->type)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
237
src/parser.cpp
237
src/parser.cpp
|
@ -2842,20 +2842,231 @@ void normalize_parent_ptrs(AstNode *node) {
|
||||||
ast_visit_node_children(node, normalize_parent_ptrs_visit, nullptr);
|
ast_visit_node_children(node, normalize_parent_ptrs_visit, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
static AstNode *clone_node(AstNode *old_node) {
|
static void clone_subtree_list(ZigList<AstNode *> *dest, ZigList<AstNode *> *src, uint32_t *next_node_index) {
|
||||||
|
memset(dest, 0, sizeof(ZigList<AstNode *>));
|
||||||
|
dest->resize(src->length);
|
||||||
|
for (int i = 0; i < src->length; i += 1) {
|
||||||
|
dest->at(i) = ast_clone_subtree(src->at(i), next_node_index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void clone_subtree_list_ptr(ZigList<AstNode *> **dest_ptr, ZigList<AstNode *> *src,
|
||||||
|
uint32_t *next_node_index)
|
||||||
|
{
|
||||||
|
if (src) {
|
||||||
|
ZigList<AstNode *> *dest = allocate<ZigList<AstNode *>>(1);
|
||||||
|
*dest_ptr = dest;
|
||||||
|
clone_subtree_list(dest, src, next_node_index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void clone_subtree_field(AstNode **dest, AstNode *src, uint32_t *next_node_index) {
|
||||||
|
*dest = ast_clone_subtree(src, next_node_index);
|
||||||
|
(*dest)->parent_field = dest;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void clone_subtree_tld(TopLevelDecl *dest, TopLevelDecl *src, uint32_t *next_node_index) {
|
||||||
|
clone_subtree_list_ptr(&dest->directives, src->directives, next_node_index);
|
||||||
|
}
|
||||||
|
|
||||||
|
AstNode *ast_clone_subtree(AstNode *old_node, uint32_t *next_node_index) {
|
||||||
AstNode *new_node = allocate_nonzero<AstNode>(1);
|
AstNode *new_node = allocate_nonzero<AstNode>(1);
|
||||||
memcpy(new_node, old_node, sizeof(AstNode));
|
memcpy(new_node, old_node, sizeof(AstNode));
|
||||||
return new_node;
|
new_node->create_index = *next_node_index;
|
||||||
}
|
*next_node_index += 1;
|
||||||
|
|
||||||
static void ast_clone_subtree_visit(AstNode **node, void *context) {
|
switch (new_node->type) {
|
||||||
*node = clone_node(*node);
|
case NodeTypeRoot:
|
||||||
(*node)->parent_field = node;
|
clone_subtree_list(&new_node->data.root.top_level_decls, &old_node->data.root.top_level_decls,
|
||||||
ast_visit_node_children(*node, ast_clone_subtree_visit, nullptr);
|
next_node_index);
|
||||||
}
|
break;
|
||||||
|
case NodeTypeFnProto:
|
||||||
AstNode *ast_clone_subtree(AstNode *old_node) {
|
clone_subtree_tld(&new_node->data.fn_proto.top_level_decl, &old_node->data.fn_proto.top_level_decl,
|
||||||
AstNode *new_node = clone_node(old_node);
|
next_node_index);
|
||||||
ast_visit_node_children(new_node, ast_clone_subtree_visit, nullptr);
|
clone_subtree_field(&new_node->data.fn_proto.return_type, old_node->data.fn_proto.return_type,
|
||||||
|
next_node_index);
|
||||||
|
clone_subtree_list(&new_node->data.fn_proto.generic_params,
|
||||||
|
&old_node->data.fn_proto.generic_params, next_node_index);
|
||||||
|
clone_subtree_list(&new_node->data.fn_proto.params, &old_node->data.fn_proto.params,
|
||||||
|
next_node_index);
|
||||||
|
|
||||||
|
break;
|
||||||
|
case NodeTypeFnDef:
|
||||||
|
clone_subtree_field(&new_node->data.fn_def.fn_proto, old_node->data.fn_def.fn_proto, next_node_index);
|
||||||
|
new_node->data.fn_def.fn_proto->data.fn_proto.fn_def_node = new_node;
|
||||||
|
clone_subtree_field(&new_node->data.fn_def.body, old_node->data.fn_def.body, next_node_index);
|
||||||
|
break;
|
||||||
|
case NodeTypeFnDecl:
|
||||||
|
clone_subtree_field(&new_node->data.fn_decl.fn_proto, old_node->data.fn_decl.fn_proto,
|
||||||
|
next_node_index);
|
||||||
|
break;
|
||||||
|
case NodeTypeParamDecl:
|
||||||
|
clone_subtree_field(&new_node->data.param_decl.type, old_node->data.param_decl.type, next_node_index);
|
||||||
|
break;
|
||||||
|
case NodeTypeBlock:
|
||||||
|
clone_subtree_list(&new_node->data.block.statements, &old_node->data.block.statements,
|
||||||
|
next_node_index);
|
||||||
|
break;
|
||||||
|
case NodeTypeDirective:
|
||||||
|
clone_subtree_field(&new_node->data.directive.expr, old_node->data.directive.expr, next_node_index);
|
||||||
|
break;
|
||||||
|
case NodeTypeReturnExpr:
|
||||||
|
clone_subtree_field(&new_node->data.return_expr.expr, old_node->data.return_expr.expr, next_node_index);
|
||||||
|
break;
|
||||||
|
case NodeTypeDefer:
|
||||||
|
clone_subtree_field(&new_node->data.defer.expr, old_node->data.defer.expr, next_node_index);
|
||||||
|
break;
|
||||||
|
case NodeTypeVariableDeclaration:
|
||||||
|
clone_subtree_list_ptr(&new_node->data.variable_declaration.top_level_decl.directives,
|
||||||
|
old_node->data.variable_declaration.top_level_decl.directives, next_node_index);
|
||||||
|
clone_subtree_field(&new_node->data.variable_declaration.type, old_node->data.variable_declaration.type, next_node_index);
|
||||||
|
clone_subtree_field(&new_node->data.variable_declaration.expr, old_node->data.variable_declaration.expr, next_node_index);
|
||||||
|
break;
|
||||||
|
case NodeTypeTypeDecl:
|
||||||
|
clone_subtree_list_ptr(&new_node->data.type_decl.top_level_decl.directives,
|
||||||
|
old_node->data.type_decl.top_level_decl.directives, next_node_index);
|
||||||
|
clone_subtree_field(&new_node->data.type_decl.child_type, old_node->data.type_decl.child_type, next_node_index);
|
||||||
|
break;
|
||||||
|
case NodeTypeErrorValueDecl:
|
||||||
|
// none
|
||||||
|
break;
|
||||||
|
case NodeTypeBinOpExpr:
|
||||||
|
clone_subtree_field(&new_node->data.bin_op_expr.op1, old_node->data.bin_op_expr.op1, next_node_index);
|
||||||
|
clone_subtree_field(&new_node->data.bin_op_expr.op2, old_node->data.bin_op_expr.op2, next_node_index);
|
||||||
|
break;
|
||||||
|
case NodeTypeUnwrapErrorExpr:
|
||||||
|
clone_subtree_field(&new_node->data.unwrap_err_expr.op1, old_node->data.unwrap_err_expr.op1, next_node_index);
|
||||||
|
clone_subtree_field(&new_node->data.unwrap_err_expr.symbol, old_node->data.unwrap_err_expr.symbol, next_node_index);
|
||||||
|
clone_subtree_field(&new_node->data.unwrap_err_expr.op2, old_node->data.unwrap_err_expr.op2, next_node_index);
|
||||||
|
break;
|
||||||
|
case NodeTypeNumberLiteral:
|
||||||
|
// none
|
||||||
|
break;
|
||||||
|
case NodeTypeStringLiteral:
|
||||||
|
// none
|
||||||
|
break;
|
||||||
|
case NodeTypeCharLiteral:
|
||||||
|
// none
|
||||||
|
break;
|
||||||
|
case NodeTypeSymbol:
|
||||||
|
// none
|
||||||
|
break;
|
||||||
|
case NodeTypePrefixOpExpr:
|
||||||
|
clone_subtree_field(&new_node->data.prefix_op_expr.primary_expr, old_node->data.prefix_op_expr.primary_expr, next_node_index);
|
||||||
|
break;
|
||||||
|
case NodeTypeFnCallExpr:
|
||||||
|
clone_subtree_field(&new_node->data.fn_call_expr.fn_ref_expr, old_node->data.fn_call_expr.fn_ref_expr, next_node_index);
|
||||||
|
clone_subtree_list(&new_node->data.fn_call_expr.params, &old_node->data.fn_call_expr.params, next_node_index);
|
||||||
|
break;
|
||||||
|
case NodeTypeArrayAccessExpr:
|
||||||
|
clone_subtree_field(&new_node->data.array_access_expr.array_ref_expr, old_node->data.array_access_expr.array_ref_expr, next_node_index);
|
||||||
|
clone_subtree_field(&new_node->data.array_access_expr.subscript, old_node->data.array_access_expr.subscript, next_node_index);
|
||||||
|
break;
|
||||||
|
case NodeTypeSliceExpr:
|
||||||
|
clone_subtree_field(&new_node->data.slice_expr.array_ref_expr, old_node->data.slice_expr.array_ref_expr, next_node_index);
|
||||||
|
clone_subtree_field(&new_node->data.slice_expr.start, old_node->data.slice_expr.start, next_node_index);
|
||||||
|
clone_subtree_field(&new_node->data.slice_expr.end, old_node->data.slice_expr.end, next_node_index);
|
||||||
|
break;
|
||||||
|
case NodeTypeFieldAccessExpr:
|
||||||
|
clone_subtree_field(&new_node->data.field_access_expr.struct_expr, old_node->data.field_access_expr.struct_expr, next_node_index);
|
||||||
|
break;
|
||||||
|
case NodeTypeUse:
|
||||||
|
clone_subtree_field(&new_node->data.use.expr, old_node->data.use.expr, next_node_index);
|
||||||
|
clone_subtree_list_ptr(&new_node->data.use.top_level_decl.directives,
|
||||||
|
old_node->data.use.top_level_decl.directives, next_node_index);
|
||||||
|
break;
|
||||||
|
case NodeTypeBoolLiteral:
|
||||||
|
// none
|
||||||
|
break;
|
||||||
|
case NodeTypeNullLiteral:
|
||||||
|
// none
|
||||||
|
break;
|
||||||
|
case NodeTypeUndefinedLiteral:
|
||||||
|
// none
|
||||||
|
break;
|
||||||
|
case NodeTypeIfBoolExpr:
|
||||||
|
clone_subtree_field(&new_node->data.if_bool_expr.condition, old_node->data.if_bool_expr.condition, next_node_index);
|
||||||
|
clone_subtree_field(&new_node->data.if_bool_expr.then_block, old_node->data.if_bool_expr.then_block, next_node_index);
|
||||||
|
clone_subtree_field(&new_node->data.if_bool_expr.else_node, old_node->data.if_bool_expr.else_node, next_node_index);
|
||||||
|
break;
|
||||||
|
case NodeTypeIfVarExpr:
|
||||||
|
clone_subtree_field(&new_node->data.if_var_expr.var_decl.type, old_node->data.if_var_expr.var_decl.type, next_node_index);
|
||||||
|
clone_subtree_field(&new_node->data.if_var_expr.var_decl.expr, old_node->data.if_var_expr.var_decl.expr, next_node_index);
|
||||||
|
clone_subtree_field(&new_node->data.if_var_expr.then_block, old_node->data.if_var_expr.then_block, next_node_index);
|
||||||
|
clone_subtree_field(&new_node->data.if_var_expr.else_node, old_node->data.if_var_expr.else_node, next_node_index);
|
||||||
|
break;
|
||||||
|
case NodeTypeWhileExpr:
|
||||||
|
clone_subtree_field(&new_node->data.while_expr.condition, old_node->data.while_expr.condition, next_node_index);
|
||||||
|
clone_subtree_field(&new_node->data.while_expr.body, old_node->data.while_expr.body, next_node_index);
|
||||||
|
break;
|
||||||
|
case NodeTypeForExpr:
|
||||||
|
clone_subtree_field(&new_node->data.for_expr.elem_node, old_node->data.for_expr.elem_node, next_node_index);
|
||||||
|
clone_subtree_field(&new_node->data.for_expr.array_expr, old_node->data.for_expr.array_expr, next_node_index);
|
||||||
|
clone_subtree_field(&new_node->data.for_expr.index_node, old_node->data.for_expr.index_node, next_node_index);
|
||||||
|
clone_subtree_field(&new_node->data.for_expr.body, old_node->data.for_expr.body, next_node_index);
|
||||||
|
break;
|
||||||
|
case NodeTypeSwitchExpr:
|
||||||
|
clone_subtree_field(&new_node->data.switch_expr.expr, old_node->data.switch_expr.expr, next_node_index);
|
||||||
|
clone_subtree_list(&new_node->data.switch_expr.prongs, &old_node->data.switch_expr.prongs,
|
||||||
|
next_node_index);
|
||||||
|
break;
|
||||||
|
case NodeTypeSwitchProng:
|
||||||
|
clone_subtree_list(&new_node->data.switch_prong.items, &old_node->data.switch_prong.items,
|
||||||
|
next_node_index);
|
||||||
|
clone_subtree_field(&new_node->data.switch_prong.var_symbol, old_node->data.switch_prong.var_symbol, next_node_index);
|
||||||
|
clone_subtree_field(&new_node->data.switch_prong.expr, old_node->data.switch_prong.expr, next_node_index);
|
||||||
|
break;
|
||||||
|
case NodeTypeSwitchRange:
|
||||||
|
clone_subtree_field(&new_node->data.switch_range.start, old_node->data.switch_range.start, next_node_index);
|
||||||
|
clone_subtree_field(&new_node->data.switch_range.end, old_node->data.switch_range.end, next_node_index);
|
||||||
|
break;
|
||||||
|
case NodeTypeLabel:
|
||||||
|
// none
|
||||||
|
break;
|
||||||
|
case NodeTypeGoto:
|
||||||
|
// none
|
||||||
|
break;
|
||||||
|
case NodeTypeBreak:
|
||||||
|
// none
|
||||||
|
break;
|
||||||
|
case NodeTypeContinue:
|
||||||
|
// none
|
||||||
|
break;
|
||||||
|
case NodeTypeAsmExpr:
|
||||||
|
zig_panic("TODO");
|
||||||
|
break;
|
||||||
|
case NodeTypeStructDecl:
|
||||||
|
clone_subtree_list(&new_node->data.struct_decl.fields, &old_node->data.struct_decl.fields,
|
||||||
|
next_node_index);
|
||||||
|
clone_subtree_list(&new_node->data.struct_decl.fns, &old_node->data.struct_decl.fns,
|
||||||
|
next_node_index);
|
||||||
|
clone_subtree_list_ptr(&new_node->data.struct_decl.top_level_decl.directives,
|
||||||
|
old_node->data.struct_decl.top_level_decl.directives, next_node_index);
|
||||||
|
break;
|
||||||
|
case NodeTypeStructField:
|
||||||
|
clone_subtree_field(&new_node->data.struct_field.type, old_node->data.struct_field.type, next_node_index);
|
||||||
|
clone_subtree_list_ptr(&new_node->data.struct_field.top_level_decl.directives,
|
||||||
|
old_node->data.struct_field.top_level_decl.directives, next_node_index);
|
||||||
|
break;
|
||||||
|
case NodeTypeContainerInitExpr:
|
||||||
|
clone_subtree_field(&new_node->data.container_init_expr.type, old_node->data.container_init_expr.type, next_node_index);
|
||||||
|
clone_subtree_list(&new_node->data.container_init_expr.entries,
|
||||||
|
&old_node->data.container_init_expr.entries, next_node_index);
|
||||||
|
break;
|
||||||
|
case NodeTypeStructValueField:
|
||||||
|
clone_subtree_field(&new_node->data.struct_val_field.expr, old_node->data.struct_val_field.expr, next_node_index);
|
||||||
|
break;
|
||||||
|
case NodeTypeArrayType:
|
||||||
|
clone_subtree_field(&new_node->data.array_type.size, old_node->data.array_type.size, next_node_index);
|
||||||
|
clone_subtree_field(&new_node->data.array_type.child_type, old_node->data.array_type.child_type, next_node_index);
|
||||||
|
break;
|
||||||
|
case NodeTypeErrorType:
|
||||||
|
// none
|
||||||
|
break;
|
||||||
|
case NodeTypeTypeLiteral:
|
||||||
|
// none
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
return new_node;
|
return new_node;
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,7 +24,7 @@ void ast_print(AstNode *node, int indent);
|
||||||
|
|
||||||
void normalize_parent_ptrs(AstNode *node);
|
void normalize_parent_ptrs(AstNode *node);
|
||||||
|
|
||||||
AstNode *ast_clone_subtree(AstNode *node);
|
AstNode *ast_clone_subtree(AstNode *node, uint32_t *next_node_index);
|
||||||
void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *context), void *context);
|
void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *context), void *context);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
31
std/rand.zig
31
std/rand.zig
|
@ -1,11 +1,26 @@
|
||||||
// Mersenne Twister
|
// Mersenne Twister
|
||||||
const ARRAY_SIZE = 624;
|
const ARRAY_SIZE = 624;
|
||||||
|
|
||||||
/// Use `rand_init` to initialize this state.
|
/// Use `init` to initialize this state.
|
||||||
pub struct Rand {
|
pub struct Rand {
|
||||||
array: [ARRAY_SIZE]u32,
|
array: [ARRAY_SIZE]u32,
|
||||||
index: isize,
|
index: isize,
|
||||||
|
|
||||||
|
/// Initialize random state with the given seed.
|
||||||
|
pub fn init(seed: u32) -> Rand {
|
||||||
|
var r: Rand = undefined;
|
||||||
|
r.index = 0;
|
||||||
|
r.array[0] = seed;
|
||||||
|
var i : isize = 1;
|
||||||
|
var prev_value: u64 = seed;
|
||||||
|
while (i < ARRAY_SIZE) {
|
||||||
|
r.array[i] = u32((prev_value ^ (prev_value << 30)) * 0x6c078965 + u32(i));
|
||||||
|
prev_value = r.array[i];
|
||||||
|
i += 1;
|
||||||
|
}
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
/// Get 32 bits of randomness.
|
/// Get 32 bits of randomness.
|
||||||
pub fn get_u32(r: &Rand) -> u32 {
|
pub fn get_u32(r: &Rand) -> u32 {
|
||||||
if (r.index == 0) {
|
if (r.index == 0) {
|
||||||
|
@ -85,20 +100,6 @@ pub struct Rand {
|
||||||
return bytes_left;
|
return bytes_left;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Initialize random state with the given seed.
|
|
||||||
pub fn init(seed: u32) -> Rand {
|
|
||||||
var r: Rand = undefined;
|
|
||||||
r.index = 0;
|
|
||||||
r.array[0] = seed;
|
|
||||||
var i : isize = 1;
|
|
||||||
var prev_value: u64 = seed;
|
|
||||||
while (i < ARRAY_SIZE) {
|
|
||||||
r.array[i] = u32((prev_value ^ (prev_value << 30)) * 0x6c078965 + u32(i));
|
|
||||||
prev_value = r.array[i];
|
|
||||||
i += 1;
|
|
||||||
}
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#attribute("test")
|
#attribute("test")
|
||||||
|
|
|
@ -515,6 +515,7 @@ three)";
|
||||||
#attribute("test")
|
#attribute("test")
|
||||||
fn simple_generic_fn() {
|
fn simple_generic_fn() {
|
||||||
assert(max(i32)(3, -1) == 3);
|
assert(max(i32)(3, -1) == 3);
|
||||||
|
assert(max(f32)(0.123, 0.456) == 0.456);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn max(T: type)(a: T, b: T) -> T {
|
fn max(T: type)(a: T, b: T) -> T {
|
||||||
|
@ -530,6 +531,11 @@ fn constant_equal_function_pointers() {
|
||||||
|
|
||||||
fn empty_fn() {}
|
fn empty_fn() {}
|
||||||
|
|
||||||
|
#attribute("test")
|
||||||
|
fn generic_function_equality() {
|
||||||
|
assert(max(i32) == max(i32));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
fn assert(b: bool) {
|
fn assert(b: bool) {
|
||||||
if (!b) unreachable{}
|
if (!b) unreachable{}
|
||||||
|
|
Loading…
Reference in New Issue