remove compiler directives
* add `setFnTest`, `setFnVisible`, `setFnStaticEval`, `setFnNoInline` builtin functions to replace previous directive functionality * add `coldcc` and `nakedcc` as keywords which can be used as part of a function prototype. * `setDebugSafety` builtin can be used to set debug safety features at a per block scope level. * closes #169
This commit is contained in:
parent
e5fd8efcb6
commit
b581da41f8
|
@ -3,9 +3,11 @@
|
|||
## Grammar
|
||||
|
||||
```
|
||||
Root = many(TopLevelDecl) "EOF"
|
||||
Root = many(TopLevelItem) "EOF"
|
||||
|
||||
TopLevelDecl = many(Directive) option(VisibleMod) (FnDef | ExternDecl | ContainerDecl | GlobalVarDecl | ErrorValueDecl | TypeDecl | UseDecl)
|
||||
TopLevelItem = ErrorValueDecl | Block | TopLevelDecl
|
||||
|
||||
TopLevelDecl = option(VisibleMod) (FnDef | ExternDecl | ContainerDecl | GlobalVarDecl | TypeDecl | UseDecl)
|
||||
|
||||
TypeDecl = "type" Symbol "=" TypeExpr ";"
|
||||
|
||||
|
@ -17,7 +19,7 @@ VariableDeclaration = ("var" | "const") Symbol option(":" TypeExpr) "=" Expressi
|
|||
|
||||
ContainerDecl = ("struct" | "enum" | "union") Symbol option(ParamDeclList) "{" many(StructMember) "}"
|
||||
|
||||
StructMember = many(Directive) option(VisibleMod) (StructField | FnDef | GlobalVarDecl | ContainerDecl)
|
||||
StructMember = (StructField | FnDef | GlobalVarDecl | ContainerDecl)
|
||||
|
||||
StructField = Symbol option(":" Expression) ",")
|
||||
|
||||
|
@ -25,9 +27,7 @@ UseDecl = "use" Expression ";"
|
|||
|
||||
ExternDecl = "extern" (FnProto | VariableDeclaration) ";"
|
||||
|
||||
FnProto = "fn" option(Symbol) ParamDeclList option("->" TypeExpr)
|
||||
|
||||
Directive = "#" Symbol "(" Expression ")"
|
||||
FnProto = option("coldcc" | "nakedcc") "fn" option(Symbol) ParamDeclList option("->" TypeExpr)
|
||||
|
||||
VisibleMod = "pub" | "export"
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@ if exists("b:current_syntax")
|
|||
endif
|
||||
let b:current_syntax = "zig"
|
||||
|
||||
syn keyword zigStorage const var extern export pub noalias inline noinline
|
||||
syn keyword zigStorage const var extern export pub noalias inline nakedcc coldcc
|
||||
syn keyword zigStructure struct enum union
|
||||
syn keyword zigStatement goto break return continue asm defer
|
||||
syn keyword zigConditional if else switch
|
||||
|
|
|
@ -129,7 +129,6 @@ enum TldResolution {
|
|||
struct TopLevelDecl {
|
||||
// populated by parser
|
||||
Buf *name;
|
||||
ZigList<AstNode *> *directives;
|
||||
VisibMod visib_mod;
|
||||
|
||||
// populated by semantic analyzer
|
||||
|
@ -153,7 +152,6 @@ enum NodeType {
|
|||
NodeTypeFnDecl,
|
||||
NodeTypeParamDecl,
|
||||
NodeTypeBlock,
|
||||
NodeTypeDirective,
|
||||
NodeTypeReturnExpr,
|
||||
NodeTypeDefer,
|
||||
NodeTypeVariableDeclaration,
|
||||
|
@ -210,6 +208,8 @@ struct AstNodeFnProto {
|
|||
bool is_var_args;
|
||||
bool is_extern;
|
||||
bool is_inline;
|
||||
bool is_coldcc;
|
||||
bool is_nakedcc;
|
||||
|
||||
// populated by semantic analyzer:
|
||||
|
||||
|
@ -459,11 +459,6 @@ struct AstNodeFieldAccessExpr {
|
|||
AstNode *container_init_expr_node;
|
||||
};
|
||||
|
||||
struct AstNodeDirective {
|
||||
Buf *name;
|
||||
AstNode *expr;
|
||||
};
|
||||
|
||||
enum PrefixOp {
|
||||
PrefixOpInvalid,
|
||||
PrefixOpBoolNot,
|
||||
|
@ -802,7 +797,6 @@ struct AstNode {
|
|||
AstNodeErrorValueDecl error_value_decl;
|
||||
AstNodeBinOpExpr bin_op_expr;
|
||||
AstNodeUnwrapErrorExpr unwrap_err_expr;
|
||||
AstNodeDirective directive;
|
||||
AstNodePrefixOpExpr prefix_op_expr;
|
||||
AstNodeFnCallExpr fn_call_expr;
|
||||
AstNodeArrayAccessExpr array_access_expr;
|
||||
|
@ -1109,10 +1103,14 @@ struct FnTableEntry {
|
|||
WantPure want_pure;
|
||||
AstNode *want_pure_attr_node;
|
||||
AstNode *want_pure_return_type;
|
||||
bool safety_off;
|
||||
FnInline fn_inline;
|
||||
FnAnalState anal_state;
|
||||
|
||||
AstNode *fn_no_inline_set_node;
|
||||
AstNode *fn_export_set_node;
|
||||
AstNode *fn_test_set_node;
|
||||
AstNode *fn_static_eval_set_node;
|
||||
|
||||
ZigList<AstNode *> cast_alloca_list;
|
||||
ZigList<StructValExprCodeGen *> struct_val_expr_alloca_list;
|
||||
ZigList<VariableTableEntry *> variable_list;
|
||||
|
@ -1154,6 +1152,11 @@ enum BuiltinFnId {
|
|||
BuiltinFnIdTruncate,
|
||||
BuiltinFnIdIntType,
|
||||
BuiltinFnIdUnreachable,
|
||||
BuiltinFnIdSetFnTest,
|
||||
BuiltinFnIdSetFnVisible,
|
||||
BuiltinFnIdSetFnStaticEval,
|
||||
BuiltinFnIdSetFnNoInline,
|
||||
BuiltinFnIdSetDebugSafety,
|
||||
};
|
||||
|
||||
struct BuiltinFnEntry {
|
||||
|
@ -1373,6 +1376,7 @@ struct BlockContext {
|
|||
bool codegen_excluded;
|
||||
|
||||
bool safety_off;
|
||||
AstNode *safety_set_node;
|
||||
};
|
||||
|
||||
enum AtomicOrder {
|
||||
|
|
327
src/analyze.cpp
327
src/analyze.cpp
|
@ -75,7 +75,6 @@ static AstNode *first_executing_node(AstNode *node) {
|
|||
case NodeTypeFnDecl:
|
||||
case NodeTypeParamDecl:
|
||||
case NodeTypeBlock:
|
||||
case NodeTypeDirective:
|
||||
case NodeTypeReturnExpr:
|
||||
case NodeTypeDefer:
|
||||
case NodeTypeVariableDeclaration:
|
||||
|
@ -1123,6 +1122,28 @@ static bool resolve_const_expr_bool(CodeGen *g, ImportTableEntry *import, BlockC
|
|||
return true;
|
||||
}
|
||||
|
||||
static FnTableEntry *resolve_const_expr_fn(CodeGen *g, ImportTableEntry *import, BlockContext *context,
|
||||
AstNode **node)
|
||||
{
|
||||
TypeTableEntry *resolved_type = analyze_expression(g, import, context, nullptr, *node);
|
||||
|
||||
if (resolved_type->id == TypeTableEntryIdInvalid) {
|
||||
return nullptr;
|
||||
} else if (resolved_type->id == TypeTableEntryIdFn) {
|
||||
ConstExprValue *const_val = &get_resolved_expr(*node)->const_val;
|
||||
|
||||
if (!const_val->ok) {
|
||||
add_node_error(g, *node, buf_sprintf("unable to evaluate constant expression"));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return const_val->data.x_fn;
|
||||
} else {
|
||||
add_node_error(g, *node, buf_sprintf("expected function, got '%s'", buf_ptr(&resolved_type->name)));
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
static void resolve_function_proto(CodeGen *g, AstNode *node, FnTableEntry *fn_table_entry,
|
||||
ImportTableEntry *import, BlockContext *containing_context)
|
||||
{
|
||||
|
@ -1133,85 +1154,6 @@ static void resolve_function_proto(CodeGen *g, AstNode *node, FnTableEntry *fn_t
|
|||
return;
|
||||
}
|
||||
|
||||
bool is_cold = false;
|
||||
bool is_naked = false;
|
||||
bool is_test = false;
|
||||
bool is_noinline = false;
|
||||
|
||||
if (fn_proto->top_level_decl.directives) {
|
||||
for (size_t i = 0; i < fn_proto->top_level_decl.directives->length; i += 1) {
|
||||
AstNode *directive_node = fn_proto->top_level_decl.directives->at(i);
|
||||
Buf *name = directive_node->data.directive.name;
|
||||
|
||||
if (buf_eql_str(name, "attribute")) {
|
||||
if (fn_table_entry->fn_def_node) {
|
||||
Buf *attr_name = resolve_const_expr_str(g, import, import->block_context,
|
||||
&directive_node->data.directive.expr);
|
||||
if (attr_name) {
|
||||
if (buf_eql_str(attr_name, "naked")) {
|
||||
is_naked = true;
|
||||
} else if (buf_eql_str(attr_name, "noinline")) {
|
||||
is_noinline = true;
|
||||
} else if (buf_eql_str(attr_name, "cold")) {
|
||||
is_cold = true;
|
||||
} else if (buf_eql_str(attr_name, "test")) {
|
||||
is_test = true;
|
||||
g->test_fn_count += 1;
|
||||
} else {
|
||||
add_node_error(g, directive_node,
|
||||
buf_sprintf("invalid function attribute: '%s'", buf_ptr(name)));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
add_node_error(g, directive_node,
|
||||
buf_sprintf("invalid function attribute: '%s'", buf_ptr(name)));
|
||||
}
|
||||
} else if (buf_eql_str(name, "debug_safety")) {
|
||||
if (!fn_table_entry->fn_def_node) {
|
||||
add_node_error(g, directive_node,
|
||||
buf_sprintf("#debug_safety valid only on function definitions"));
|
||||
} else {
|
||||
bool enable;
|
||||
bool ok = resolve_const_expr_bool(g, import, import->block_context,
|
||||
&directive_node->data.directive.expr, &enable);
|
||||
if (ok && !enable) {
|
||||
fn_table_entry->safety_off = true;
|
||||
}
|
||||
}
|
||||
} else if (buf_eql_str(name, "condition")) {
|
||||
if (fn_proto->top_level_decl.visib_mod == VisibModExport) {
|
||||
bool include;
|
||||
bool ok = resolve_const_expr_bool(g, import, import->block_context,
|
||||
&directive_node->data.directive.expr, &include);
|
||||
if (ok && !include) {
|
||||
fn_proto->top_level_decl.visib_mod = VisibModPub;
|
||||
}
|
||||
} else {
|
||||
add_node_error(g, directive_node,
|
||||
buf_sprintf("#condition valid only on exported symbols"));
|
||||
}
|
||||
} else if (buf_eql_str(name, "static_eval_enable")) {
|
||||
if (!fn_table_entry->fn_def_node) {
|
||||
add_node_error(g, directive_node,
|
||||
buf_sprintf("#static_val_enable valid only on function definitions"));
|
||||
} else {
|
||||
bool enable;
|
||||
bool ok = resolve_const_expr_bool(g, import, import->block_context,
|
||||
&directive_node->data.directive.expr, &enable);
|
||||
if (!ok || !enable) {
|
||||
fn_table_entry->want_pure = WantPureFalse;
|
||||
} else if (ok && enable) {
|
||||
fn_table_entry->want_pure = WantPureTrue;
|
||||
fn_table_entry->want_pure_attr_node = directive_node->data.directive.expr;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
add_node_error(g, directive_node,
|
||||
buf_sprintf("invalid directive: '%s'", buf_ptr(name)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool is_internal = (fn_proto->top_level_decl.visib_mod != VisibModExport);
|
||||
bool is_c_compat = !is_internal || fn_proto->is_extern;
|
||||
fn_table_entry->internal_linkage = !is_c_compat;
|
||||
|
@ -1219,24 +1161,17 @@ static void resolve_function_proto(CodeGen *g, AstNode *node, FnTableEntry *fn_t
|
|||
|
||||
|
||||
TypeTableEntry *fn_type = analyze_fn_proto_type(g, import, containing_context, nullptr, node,
|
||||
is_naked, is_cold, fn_table_entry);
|
||||
fn_proto->is_nakedcc, fn_proto->is_coldcc, fn_table_entry);
|
||||
|
||||
fn_table_entry->type_entry = fn_type;
|
||||
fn_table_entry->is_test = is_test;
|
||||
|
||||
if (fn_type->id == TypeTableEntryIdInvalid) {
|
||||
fn_proto->skip = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (fn_proto->is_inline && is_noinline) {
|
||||
add_node_error(g, node, buf_sprintf("function is both inline and noinline"));
|
||||
fn_proto->skip = true;
|
||||
return;
|
||||
} else if (fn_proto->is_inline) {
|
||||
if (fn_proto->is_inline) {
|
||||
fn_table_entry->fn_inline = FnInlineAlways;
|
||||
} else if (is_noinline) {
|
||||
fn_table_entry->fn_inline = FnInlineNever;
|
||||
}
|
||||
|
||||
|
||||
|
@ -1881,7 +1816,6 @@ static void resolve_top_level_decl(CodeGen *g, AstNode *node, bool pointer_only)
|
|||
zig_panic("TODO resolve_top_level_decl NodeTypeUse");
|
||||
break;
|
||||
case NodeTypeFnDef:
|
||||
case NodeTypeDirective:
|
||||
case NodeTypeParamDecl:
|
||||
case NodeTypeFnDecl:
|
||||
case NodeTypeReturnExpr:
|
||||
|
@ -2406,13 +2340,11 @@ BlockContext *new_block_context(AstNode *node, BlockContext *parent) {
|
|||
context->parent_loop_node = parent->parent_loop_node;
|
||||
context->c_import_buf = parent->c_import_buf;
|
||||
context->codegen_excluded = parent->codegen_excluded;
|
||||
context->safety_off = parent->safety_off;
|
||||
}
|
||||
|
||||
if (node && node->type == NodeTypeFnDef) {
|
||||
AstNode *fn_proto_node = node->data.fn_def.fn_proto;
|
||||
context->fn_entry = fn_proto_node->data.fn_proto.fn_table_entry;
|
||||
context->safety_off = context->fn_entry->safety_off;
|
||||
} else if (parent) {
|
||||
context->fn_entry = parent->fn_entry;
|
||||
}
|
||||
|
@ -5246,6 +5178,203 @@ static TypeTableEntry *analyze_int_type(CodeGen *g, ImportTableEntry *import,
|
|||
|
||||
}
|
||||
|
||||
static TypeTableEntry *analyze_set_fn_test(CodeGen *g, ImportTableEntry *import,
|
||||
BlockContext *context, AstNode *node)
|
||||
{
|
||||
AstNode **fn_node = &node->data.fn_call_expr.params.at(0);
|
||||
AstNode **value_node = &node->data.fn_call_expr.params.at(1);
|
||||
|
||||
FnTableEntry *fn_entry = resolve_const_expr_fn(g, import, context, fn_node);
|
||||
if (!fn_entry) {
|
||||
return g->builtin_types.entry_invalid;
|
||||
}
|
||||
|
||||
bool ok = resolve_const_expr_bool(g, import, context, value_node, &fn_entry->is_test);
|
||||
if (!ok) {
|
||||
return g->builtin_types.entry_invalid;
|
||||
}
|
||||
|
||||
if (fn_entry->fn_test_set_node) {
|
||||
ErrorMsg *msg = add_node_error(g, node, buf_sprintf("function test attribute set twice"));
|
||||
add_error_note(g, msg, fn_entry->fn_test_set_node, buf_sprintf("first set here"));
|
||||
return g->builtin_types.entry_invalid;
|
||||
}
|
||||
fn_entry->fn_test_set_node = node;
|
||||
|
||||
g->test_fn_count += 1;
|
||||
return g->builtin_types.entry_void;
|
||||
}
|
||||
|
||||
static TypeTableEntry *analyze_set_fn_no_inline(CodeGen *g, ImportTableEntry *import,
|
||||
BlockContext *context, AstNode *node)
|
||||
{
|
||||
AstNode **fn_node = &node->data.fn_call_expr.params.at(0);
|
||||
AstNode **value_node = &node->data.fn_call_expr.params.at(1);
|
||||
|
||||
FnTableEntry *fn_entry = resolve_const_expr_fn(g, import, context, fn_node);
|
||||
if (!fn_entry) {
|
||||
return g->builtin_types.entry_invalid;
|
||||
}
|
||||
|
||||
bool is_noinline;
|
||||
bool ok = resolve_const_expr_bool(g, import, context, value_node, &is_noinline);
|
||||
if (!ok) {
|
||||
return g->builtin_types.entry_invalid;
|
||||
}
|
||||
|
||||
if (fn_entry->fn_no_inline_set_node) {
|
||||
ErrorMsg *msg = add_node_error(g, node, buf_sprintf("function no inline attribute set twice"));
|
||||
add_error_note(g, msg, fn_entry->fn_no_inline_set_node, buf_sprintf("first set here"));
|
||||
return g->builtin_types.entry_invalid;
|
||||
}
|
||||
fn_entry->fn_no_inline_set_node = node;
|
||||
|
||||
if (fn_entry->fn_inline == FnInlineAlways) {
|
||||
add_node_error(g, node, buf_sprintf("function is both inline and noinline"));
|
||||
fn_entry->proto_node->data.fn_proto.skip = true;
|
||||
return g->builtin_types.entry_invalid;
|
||||
} else if (is_noinline) {
|
||||
fn_entry->fn_inline = FnInlineNever;
|
||||
}
|
||||
|
||||
return g->builtin_types.entry_void;
|
||||
}
|
||||
|
||||
static TypeTableEntry *analyze_set_fn_static_eval(CodeGen *g, ImportTableEntry *import,
|
||||
BlockContext *context, AstNode *node)
|
||||
{
|
||||
AstNode **fn_node = &node->data.fn_call_expr.params.at(0);
|
||||
AstNode **value_node = &node->data.fn_call_expr.params.at(1);
|
||||
|
||||
FnTableEntry *fn_entry = resolve_const_expr_fn(g, import, context, fn_node);
|
||||
if (!fn_entry) {
|
||||
return g->builtin_types.entry_invalid;
|
||||
}
|
||||
|
||||
bool want_static_eval;
|
||||
bool ok = resolve_const_expr_bool(g, import, context, value_node, &want_static_eval);
|
||||
if (!ok) {
|
||||
return g->builtin_types.entry_invalid;
|
||||
}
|
||||
|
||||
if (fn_entry->fn_static_eval_set_node) {
|
||||
ErrorMsg *msg = add_node_error(g, node, buf_sprintf("function static eval attribute set twice"));
|
||||
add_error_note(g, msg, fn_entry->fn_static_eval_set_node, buf_sprintf("first set here"));
|
||||
return g->builtin_types.entry_invalid;
|
||||
}
|
||||
fn_entry->fn_static_eval_set_node = node;
|
||||
|
||||
if (want_static_eval && !context->fn_entry->is_pure) {
|
||||
add_node_error(g, node, buf_sprintf("attribute appears too late within function"));
|
||||
return g->builtin_types.entry_invalid;
|
||||
}
|
||||
|
||||
if (want_static_eval) {
|
||||
fn_entry->want_pure = WantPureTrue;
|
||||
fn_entry->want_pure_attr_node = node;
|
||||
} else {
|
||||
fn_entry->want_pure = WantPureFalse;
|
||||
fn_entry->is_pure = false;
|
||||
}
|
||||
|
||||
return g->builtin_types.entry_void;
|
||||
}
|
||||
|
||||
static TypeTableEntry *analyze_set_fn_visible(CodeGen *g, ImportTableEntry *import,
|
||||
BlockContext *context, AstNode *node)
|
||||
{
|
||||
AstNode **fn_node = &node->data.fn_call_expr.params.at(0);
|
||||
AstNode **value_node = &node->data.fn_call_expr.params.at(1);
|
||||
|
||||
FnTableEntry *fn_entry = resolve_const_expr_fn(g, import, context, fn_node);
|
||||
if (!fn_entry) {
|
||||
return g->builtin_types.entry_invalid;
|
||||
}
|
||||
|
||||
bool want_export;
|
||||
bool ok = resolve_const_expr_bool(g, import, context, value_node, &want_export);
|
||||
if (!ok) {
|
||||
return g->builtin_types.entry_invalid;
|
||||
}
|
||||
|
||||
if (fn_entry->fn_export_set_node) {
|
||||
ErrorMsg *msg = add_node_error(g, node, buf_sprintf("function visibility set twice"));
|
||||
add_error_note(g, msg, fn_entry->fn_export_set_node, buf_sprintf("first set here"));
|
||||
return g->builtin_types.entry_invalid;
|
||||
}
|
||||
fn_entry->fn_export_set_node = node;
|
||||
|
||||
AstNodeFnProto *fn_proto = &fn_entry->proto_node->data.fn_proto;
|
||||
if (fn_proto->top_level_decl.visib_mod != VisibModExport) {
|
||||
ErrorMsg *msg = add_node_error(g, node,
|
||||
buf_sprintf("function must be marked export to set function visibility"));
|
||||
add_error_note(g, msg, fn_entry->proto_node, buf_sprintf("function declared here"));
|
||||
return g->builtin_types.entry_void;
|
||||
}
|
||||
if (!want_export) {
|
||||
fn_proto->top_level_decl.visib_mod = VisibModPub;
|
||||
}
|
||||
|
||||
return g->builtin_types.entry_void;
|
||||
}
|
||||
|
||||
static TypeTableEntry *analyze_set_debug_safety(CodeGen *g, ImportTableEntry *import,
|
||||
BlockContext *parent_context, AstNode *node)
|
||||
{
|
||||
AstNode **target_node = &node->data.fn_call_expr.params.at(0);
|
||||
AstNode **value_node = &node->data.fn_call_expr.params.at(1);
|
||||
|
||||
TypeTableEntry *target_type = analyze_expression(g, import, parent_context, nullptr, *target_node);
|
||||
BlockContext *target_context;
|
||||
ConstExprValue *const_val = &get_resolved_expr(*target_node)->const_val;
|
||||
if (target_type->id == TypeTableEntryIdInvalid) {
|
||||
return g->builtin_types.entry_invalid;
|
||||
}
|
||||
if (!const_val->ok) {
|
||||
add_node_error(g, *target_node, buf_sprintf("unable to evaluate constant expression"));
|
||||
return g->builtin_types.entry_invalid;
|
||||
}
|
||||
if (target_type->id == TypeTableEntryIdBlock) {
|
||||
target_context = const_val->data.x_block;
|
||||
} else if (target_type->id == TypeTableEntryIdFn) {
|
||||
target_context = const_val->data.x_fn->fn_def_node->data.fn_def.block_context;
|
||||
} else if (target_type->id == TypeTableEntryIdMetaType) {
|
||||
TypeTableEntry *type_arg = const_val->data.x_type;
|
||||
if (type_arg->id == TypeTableEntryIdStruct) {
|
||||
target_context = type_arg->data.structure.block_context;
|
||||
} else if (type_arg->id == TypeTableEntryIdEnum) {
|
||||
target_context = type_arg->data.enumeration.block_context;
|
||||
} else if (type_arg->id == TypeTableEntryIdUnion) {
|
||||
target_context = type_arg->data.unionation.block_context;
|
||||
} else {
|
||||
add_node_error(g, *target_node,
|
||||
buf_sprintf("expected scope reference, got type '%s'", buf_ptr(&type_arg->name)));
|
||||
return g->builtin_types.entry_invalid;
|
||||
}
|
||||
} else {
|
||||
add_node_error(g, *target_node,
|
||||
buf_sprintf("expected scope reference, got type '%s'", buf_ptr(&target_type->name)));
|
||||
return g->builtin_types.entry_invalid;
|
||||
}
|
||||
|
||||
bool want_debug_safety;
|
||||
bool ok = resolve_const_expr_bool(g, import, parent_context, value_node, &want_debug_safety);
|
||||
if (!ok) {
|
||||
return g->builtin_types.entry_invalid;
|
||||
}
|
||||
|
||||
if (target_context->safety_set_node) {
|
||||
ErrorMsg *msg = add_node_error(g, node, buf_sprintf("debug safety for scope set twice"));
|
||||
add_error_note(g, msg, target_context->safety_set_node, buf_sprintf("first set here"));
|
||||
return g->builtin_types.entry_invalid;
|
||||
}
|
||||
target_context->safety_set_node = node;
|
||||
|
||||
target_context->safety_off = !want_debug_safety;
|
||||
|
||||
return g->builtin_types.entry_void;
|
||||
}
|
||||
|
||||
static TypeTableEntry *analyze_builtin_fn_call_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
|
||||
TypeTableEntry *expected_type, AstNode *node)
|
||||
{
|
||||
|
@ -5607,6 +5736,16 @@ static TypeTableEntry *analyze_builtin_fn_call_expr(CodeGen *g, ImportTableEntry
|
|||
return analyze_int_type(g, import, context, node);
|
||||
case BuiltinFnIdUnreachable:
|
||||
return g->builtin_types.entry_unreachable;
|
||||
case BuiltinFnIdSetFnTest:
|
||||
return analyze_set_fn_test(g, import, context, node);
|
||||
case BuiltinFnIdSetFnNoInline:
|
||||
return analyze_set_fn_no_inline(g, import, context, node);
|
||||
case BuiltinFnIdSetFnStaticEval:
|
||||
return analyze_set_fn_static_eval(g, import, context, node);
|
||||
case BuiltinFnIdSetFnVisible:
|
||||
return analyze_set_fn_visible(g, import, context, node);
|
||||
case BuiltinFnIdSetDebugSafety:
|
||||
return analyze_set_debug_safety(g, import, context, node);
|
||||
}
|
||||
zig_unreachable();
|
||||
}
|
||||
|
@ -6876,7 +7015,6 @@ static TypeTableEntry *analyze_expression_pointer_only(CodeGen *g, ImportTableEn
|
|||
break;
|
||||
case NodeTypeSwitchProng:
|
||||
case NodeTypeSwitchRange:
|
||||
case NodeTypeDirective:
|
||||
case NodeTypeFnDecl:
|
||||
case NodeTypeParamDecl:
|
||||
case NodeTypeRoot:
|
||||
|
@ -7109,7 +7247,6 @@ static void scan_decls(CodeGen *g, ImportTableEntry *import, BlockContext *conte
|
|||
// error value declarations do not depend on other top level decls
|
||||
preview_error_value_decl(g, node);
|
||||
break;
|
||||
case NodeTypeDirective:
|
||||
case NodeTypeParamDecl:
|
||||
case NodeTypeFnDecl:
|
||||
case NodeTypeReturnExpr:
|
||||
|
@ -7418,7 +7555,6 @@ Expr *get_resolved_expr(AstNode *node) {
|
|||
case NodeTypeFnDef:
|
||||
case NodeTypeFnDecl:
|
||||
case NodeTypeParamDecl:
|
||||
case NodeTypeDirective:
|
||||
case NodeTypeUse:
|
||||
case NodeTypeContainerDecl:
|
||||
case NodeTypeStructField:
|
||||
|
@ -7469,7 +7605,6 @@ static TopLevelDecl *get_as_top_level_decl(AstNode *node) {
|
|||
case NodeTypeFnDecl:
|
||||
case NodeTypeParamDecl:
|
||||
case NodeTypeBlock:
|
||||
case NodeTypeDirective:
|
||||
case NodeTypeStringLiteral:
|
||||
case NodeTypeCharLiteral:
|
||||
case NodeTypeSymbol:
|
||||
|
|
|
@ -141,8 +141,6 @@ static const char *node_type_str(NodeType node_type) {
|
|||
return "ArrayAccessExpr";
|
||||
case NodeTypeSliceExpr:
|
||||
return "SliceExpr";
|
||||
case NodeTypeDirective:
|
||||
return "Directive";
|
||||
case NodeTypeReturnExpr:
|
||||
return "ReturnExpr";
|
||||
case NodeTypeDefer:
|
||||
|
@ -416,13 +414,6 @@ static void render_node(AstRender *ar, AstNode *node) {
|
|||
}
|
||||
case NodeTypeFnDef:
|
||||
{
|
||||
ZigList<AstNode *> *directives =
|
||||
node->data.fn_def.fn_proto->data.fn_proto.top_level_decl.directives;
|
||||
if (directives) {
|
||||
for (size_t i = 0; i < directives->length; i += 1) {
|
||||
render_node(ar, directives->at(i));
|
||||
}
|
||||
}
|
||||
render_node(ar, node->data.fn_def.fn_proto);
|
||||
fprintf(ar->f, " ");
|
||||
render_node(ar, node->data.fn_def.body);
|
||||
|
@ -445,11 +436,6 @@ static void render_node(AstRender *ar, AstNode *node) {
|
|||
print_indent(ar);
|
||||
fprintf(ar->f, "}");
|
||||
break;
|
||||
case NodeTypeDirective:
|
||||
fprintf(ar->f, "#%s(", buf_ptr(node->data.directive.name));
|
||||
render_node(ar, node->data.directive.expr);
|
||||
fprintf(ar->f, ")\n");
|
||||
break;
|
||||
case NodeTypeReturnExpr:
|
||||
{
|
||||
const char *return_str = return_string(node->data.return_expr.kind);
|
||||
|
|
|
@ -352,8 +352,20 @@ static LLVMValueRef get_handle_value(CodeGen *g, AstNode *source_node, LLVMValue
|
|||
}
|
||||
}
|
||||
|
||||
static bool want_debug_safety_recursive(CodeGen *g, BlockContext *context) {
|
||||
if (context->safety_set_node || !context->parent) {
|
||||
return !context->safety_off;
|
||||
}
|
||||
context->safety_off = want_debug_safety_recursive(g, context->parent);
|
||||
context->safety_set_node = context->parent->safety_set_node;
|
||||
return !context->safety_off;
|
||||
}
|
||||
|
||||
static bool want_debug_safety(CodeGen *g, AstNode *node) {
|
||||
return !g->is_release_build && !node->block_context->safety_off;
|
||||
if (g->is_release_build) {
|
||||
return false;
|
||||
}
|
||||
return want_debug_safety_recursive(g, node->block_context);
|
||||
}
|
||||
|
||||
static void gen_debug_safety_crash(CodeGen *g) {
|
||||
|
@ -709,6 +721,13 @@ static LLVMValueRef gen_builtin_fn_call_expr(CodeGen *g, AstNode *node) {
|
|||
return gen_truncate(g, node);
|
||||
case BuiltinFnIdUnreachable:
|
||||
return gen_unreachable(g, node);
|
||||
case BuiltinFnIdSetFnTest:
|
||||
case BuiltinFnIdSetFnVisible:
|
||||
case BuiltinFnIdSetFnStaticEval:
|
||||
case BuiltinFnIdSetFnNoInline:
|
||||
case BuiltinFnIdSetDebugSafety:
|
||||
// do nothing
|
||||
return nullptr;
|
||||
}
|
||||
zig_unreachable();
|
||||
}
|
||||
|
@ -3617,7 +3636,6 @@ static LLVMValueRef gen_expr(CodeGen *g, AstNode *node) {
|
|||
case NodeTypeFnDef:
|
||||
case NodeTypeFnDecl:
|
||||
case NodeTypeParamDecl:
|
||||
case NodeTypeDirective:
|
||||
case NodeTypeUse:
|
||||
case NodeTypeContainerDecl:
|
||||
case NodeTypeStructField:
|
||||
|
@ -4880,6 +4898,11 @@ static void define_builtin_fns(CodeGen *g) {
|
|||
create_builtin_fn_with_arg_count(g, BuiltinFnIdCompileErr, "compileError", 1);
|
||||
create_builtin_fn_with_arg_count(g, BuiltinFnIdIntType, "intType", 2);
|
||||
create_builtin_fn_with_arg_count(g, BuiltinFnIdUnreachable, "unreachable", 0);
|
||||
create_builtin_fn_with_arg_count(g, BuiltinFnIdSetFnTest, "setFnTest", 2);
|
||||
create_builtin_fn_with_arg_count(g, BuiltinFnIdSetFnVisible, "setFnVisible", 2);
|
||||
create_builtin_fn_with_arg_count(g, BuiltinFnIdSetFnStaticEval, "setFnStaticEval", 2);
|
||||
create_builtin_fn_with_arg_count(g, BuiltinFnIdSetFnNoInline, "setFnNoInline", 2);
|
||||
create_builtin_fn_with_arg_count(g, BuiltinFnIdSetDebugSafety, "setDebugSafety", 2);
|
||||
}
|
||||
|
||||
static void init(CodeGen *g, Buf *source_path) {
|
||||
|
|
|
@ -963,6 +963,12 @@ static bool eval_fn_call_builtin(EvalFn *ef, AstNode *node, ConstExprValue *out_
|
|||
case BuiltinFnIdCompileErr:
|
||||
case BuiltinFnIdIntType:
|
||||
zig_unreachable();
|
||||
case BuiltinFnIdSetFnTest:
|
||||
case BuiltinFnIdSetFnVisible:
|
||||
case BuiltinFnIdSetFnStaticEval:
|
||||
case BuiltinFnIdSetFnNoInline:
|
||||
case BuiltinFnIdSetDebugSafety:
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
@ -1398,7 +1404,6 @@ static bool eval_expr(EvalFn *ef, AstNode *node, ConstExprValue *out) {
|
|||
case NodeTypeUse:
|
||||
case NodeTypeAsmExpr:
|
||||
case NodeTypeParamDecl:
|
||||
case NodeTypeDirective:
|
||||
case NodeTypeTypeDecl:
|
||||
zig_unreachable();
|
||||
}
|
||||
|
|
|
@ -124,7 +124,6 @@ static AstNode *create_typed_var_decl_node(Context *c, bool is_const, const char
|
|||
node->data.variable_declaration.is_const = is_const;
|
||||
node->data.variable_declaration.top_level_decl.visib_mod = c->visib_mod;
|
||||
node->data.variable_declaration.expr = init_node;
|
||||
node->data.variable_declaration.top_level_decl.directives = nullptr;
|
||||
node->data.variable_declaration.type = type_node;
|
||||
normalize_parent_ptrs(node);
|
||||
return node;
|
||||
|
|
203
src/parser.cpp
203
src/parser.cpp
|
@ -211,8 +211,7 @@ static AstNode *ast_parse_if_expr(ParseContext *pc, size_t *token_index, bool ma
|
|||
static AstNode *ast_parse_block_expr(ParseContext *pc, size_t *token_index, bool mandatory);
|
||||
static AstNode *ast_parse_unwrap_expr(ParseContext *pc, size_t *token_index, bool mandatory);
|
||||
static AstNode *ast_parse_prefix_op_expr(ParseContext *pc, size_t *token_index, bool mandatory);
|
||||
static AstNode *ast_parse_fn_proto(ParseContext *pc, size_t *token_index, bool mandatory,
|
||||
ZigList<AstNode*> *directives, VisibMod visib_mod);
|
||||
static AstNode *ast_parse_fn_proto(ParseContext *pc, size_t *token_index, bool mandatory, VisibMod visib_mod);
|
||||
static AstNode *ast_parse_return_expr(ParseContext *pc, size_t *token_index);
|
||||
static AstNode *ast_parse_grouped_expr(ParseContext *pc, size_t *token_index, bool mandatory);
|
||||
|
||||
|
@ -233,39 +232,6 @@ static Token *ast_eat_token(ParseContext *pc, size_t *token_index, TokenId token
|
|||
return token;
|
||||
}
|
||||
|
||||
/*
|
||||
Directive = "#" "Symbol" "(" Expression ")"
|
||||
*/
|
||||
static AstNode *ast_parse_directive(ParseContext *pc, size_t *token_index) {
|
||||
Token *number_sign = ast_eat_token(pc, token_index, TokenIdNumberSign);
|
||||
|
||||
AstNode *node = ast_create_node(pc, NodeTypeDirective, number_sign);
|
||||
|
||||
Token *name_symbol = ast_eat_token(pc, token_index, TokenIdSymbol);
|
||||
|
||||
node->data.directive.name = token_buf(name_symbol);
|
||||
|
||||
node->data.directive.expr = ast_parse_grouped_expr(pc, token_index, true);
|
||||
|
||||
normalize_parent_ptrs(node);
|
||||
return node;
|
||||
}
|
||||
|
||||
static void ast_parse_directives(ParseContext *pc, size_t *token_index,
|
||||
ZigList<AstNode *> *directives)
|
||||
{
|
||||
for (;;) {
|
||||
Token *token = &pc->tokens->at(*token_index);
|
||||
if (token->id == TokenIdNumberSign) {
|
||||
AstNode *directive_node = ast_parse_directive(pc, token_index);
|
||||
directives->append(directive_node);
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
zig_unreachable();
|
||||
}
|
||||
|
||||
/*
|
||||
TypeExpr = PrefixOpExpression | "var"
|
||||
*/
|
||||
|
@ -686,7 +652,7 @@ static AstNode *ast_parse_primary_expr(ParseContext *pc, size_t *token_index, bo
|
|||
return node;
|
||||
} else if (token->id == TokenIdKeywordExtern) {
|
||||
*token_index += 1;
|
||||
AstNode *node = ast_parse_fn_proto(pc, token_index, true, nullptr, VisibModPrivate);
|
||||
AstNode *node = ast_parse_fn_proto(pc, token_index, true, VisibModPrivate);
|
||||
node->data.fn_proto.is_extern = true;
|
||||
return node;
|
||||
} else if (token->id == TokenIdAtSign) {
|
||||
|
@ -735,7 +701,7 @@ static AstNode *ast_parse_primary_expr(ParseContext *pc, size_t *token_index, bo
|
|||
return array_type_node;
|
||||
}
|
||||
|
||||
AstNode *fn_proto_node = ast_parse_fn_proto(pc, token_index, false, nullptr, VisibModPrivate);
|
||||
AstNode *fn_proto_node = ast_parse_fn_proto(pc, token_index, false, VisibModPrivate);
|
||||
if (fn_proto_node) {
|
||||
return fn_proto_node;
|
||||
}
|
||||
|
@ -1487,7 +1453,7 @@ static AstNode *ast_parse_defer_expr(ParseContext *pc, size_t *token_index) {
|
|||
VariableDeclaration : ("var" | "const") "Symbol" ("=" Expression | ":" PrefixOpExpression option("=" Expression))
|
||||
*/
|
||||
static AstNode *ast_parse_variable_declaration_expr(ParseContext *pc, size_t *token_index, bool mandatory,
|
||||
ZigList<AstNode*> *directives, VisibMod visib_mod)
|
||||
VisibMod visib_mod)
|
||||
{
|
||||
Token *first_token = &pc->tokens->at(*token_index);
|
||||
|
||||
|
@ -1509,7 +1475,6 @@ static AstNode *ast_parse_variable_declaration_expr(ParseContext *pc, size_t *to
|
|||
|
||||
node->data.variable_declaration.is_const = is_const;
|
||||
node->data.variable_declaration.top_level_decl.visib_mod = visib_mod;
|
||||
node->data.variable_declaration.top_level_decl.directives = directives;
|
||||
|
||||
Token *name_token = ast_eat_token(pc, token_index, TokenIdSymbol);
|
||||
node->data.variable_declaration.symbol = token_buf(name_token);
|
||||
|
@ -1985,8 +1950,7 @@ static AstNode *ast_parse_block(ParseContext *pc, size_t *token_index, bool mand
|
|||
if (statement_node) {
|
||||
semicolon_expected = false;
|
||||
} else {
|
||||
statement_node = ast_parse_variable_declaration_expr(pc, token_index, false,
|
||||
nullptr, VisibModPrivate);
|
||||
statement_node = ast_parse_variable_declaration_expr(pc, token_index, false, VisibModPrivate);
|
||||
if (!statement_node) {
|
||||
statement_node = ast_parse_defer_expr(pc, token_index);
|
||||
}
|
||||
|
@ -2023,25 +1987,35 @@ static AstNode *ast_parse_block(ParseContext *pc, size_t *token_index, bool mand
|
|||
}
|
||||
|
||||
/*
|
||||
FnProto = "fn" option("Symbol") ParamDeclList option("->" TypeExpr)
|
||||
FnProto = option("coldcc" | "nakedcc") "fn" option(Symbol) ParamDeclList option("->" TypeExpr)
|
||||
*/
|
||||
static AstNode *ast_parse_fn_proto(ParseContext *pc, size_t *token_index, bool mandatory,
|
||||
ZigList<AstNode*> *directives, VisibMod visib_mod)
|
||||
{
|
||||
static AstNode *ast_parse_fn_proto(ParseContext *pc, size_t *token_index, bool mandatory, VisibMod visib_mod) {
|
||||
Token *first_token = &pc->tokens->at(*token_index);
|
||||
Token *fn_token;
|
||||
|
||||
if (first_token->id != TokenIdKeywordFn) {
|
||||
if (mandatory) {
|
||||
ast_expect_token(pc, first_token, TokenIdKeywordFn);
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
bool is_coldcc = false;
|
||||
bool is_nakedcc = false;
|
||||
if (first_token->id == TokenIdKeywordColdCC) {
|
||||
*token_index += 1;
|
||||
fn_token = ast_eat_token(pc, token_index, TokenIdKeywordFn);
|
||||
is_coldcc = true;
|
||||
} else if (first_token->id == TokenIdKeywordNakedCC) {
|
||||
*token_index += 1;
|
||||
fn_token = ast_eat_token(pc, token_index, TokenIdKeywordFn);
|
||||
is_nakedcc = true;
|
||||
} else if (first_token->id == TokenIdKeywordFn) {
|
||||
fn_token = first_token;
|
||||
*token_index += 1;
|
||||
} else if (mandatory) {
|
||||
ast_expect_token(pc, first_token, TokenIdKeywordFn);
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
*token_index += 1;
|
||||
|
||||
AstNode *node = ast_create_node(pc, NodeTypeFnProto, first_token);
|
||||
AstNode *node = ast_create_node(pc, NodeTypeFnProto, fn_token);
|
||||
node->data.fn_proto.top_level_decl.visib_mod = visib_mod;
|
||||
node->data.fn_proto.top_level_decl.directives = directives;
|
||||
node->data.fn_proto.is_coldcc = is_coldcc;
|
||||
node->data.fn_proto.is_nakedcc = is_nakedcc;
|
||||
|
||||
Token *fn_name = &pc->tokens->at(*token_index);
|
||||
if (fn_name->id == TokenIdSymbol) {
|
||||
|
@ -2068,9 +2042,7 @@ static AstNode *ast_parse_fn_proto(ParseContext *pc, size_t *token_index, bool m
|
|||
/*
|
||||
FnDef = option("inline" | "extern") FnProto Block
|
||||
*/
|
||||
static AstNode *ast_parse_fn_def(ParseContext *pc, size_t *token_index, bool mandatory,
|
||||
ZigList<AstNode*> *directives, VisibMod visib_mod)
|
||||
{
|
||||
static AstNode *ast_parse_fn_def(ParseContext *pc, size_t *token_index, bool mandatory, VisibMod visib_mod) {
|
||||
Token *first_token = &pc->tokens->at(*token_index);
|
||||
bool is_inline;
|
||||
bool is_extern;
|
||||
|
@ -2087,7 +2059,7 @@ static AstNode *ast_parse_fn_def(ParseContext *pc, size_t *token_index, bool man
|
|||
is_extern = false;
|
||||
}
|
||||
|
||||
AstNode *fn_proto = ast_parse_fn_proto(pc, token_index, mandatory, directives, visib_mod);
|
||||
AstNode *fn_proto = ast_parse_fn_proto(pc, token_index, mandatory, visib_mod);
|
||||
if (!fn_proto) {
|
||||
if (is_inline || is_extern) {
|
||||
*token_index -= 1;
|
||||
|
@ -2115,9 +2087,7 @@ static AstNode *ast_parse_fn_def(ParseContext *pc, size_t *token_index, bool man
|
|||
/*
|
||||
ExternDecl = "extern" (FnProto | VariableDeclaration) ";"
|
||||
*/
|
||||
static AstNode *ast_parse_extern_decl(ParseContext *pc, size_t *token_index, bool mandatory,
|
||||
ZigList<AstNode *> *directives, VisibMod visib_mod)
|
||||
{
|
||||
static AstNode *ast_parse_extern_decl(ParseContext *pc, size_t *token_index, bool mandatory, VisibMod visib_mod) {
|
||||
Token *extern_kw = &pc->tokens->at(*token_index);
|
||||
if (extern_kw->id != TokenIdKeywordExtern) {
|
||||
if (mandatory) {
|
||||
|
@ -2128,7 +2098,7 @@ static AstNode *ast_parse_extern_decl(ParseContext *pc, size_t *token_index, boo
|
|||
}
|
||||
*token_index += 1;
|
||||
|
||||
AstNode *fn_proto_node = ast_parse_fn_proto(pc, token_index, false, directives, visib_mod);
|
||||
AstNode *fn_proto_node = ast_parse_fn_proto(pc, token_index, false, visib_mod);
|
||||
if (fn_proto_node) {
|
||||
ast_eat_token(pc, token_index, TokenIdSemicolon);
|
||||
|
||||
|
@ -2138,7 +2108,7 @@ static AstNode *ast_parse_extern_decl(ParseContext *pc, size_t *token_index, boo
|
|||
return fn_proto_node;
|
||||
}
|
||||
|
||||
AstNode *var_decl_node = ast_parse_variable_declaration_expr(pc, token_index, false, directives, visib_mod);
|
||||
AstNode *var_decl_node = ast_parse_variable_declaration_expr(pc, token_index, false, visib_mod);
|
||||
if (var_decl_node) {
|
||||
ast_eat_token(pc, token_index, TokenIdSemicolon);
|
||||
|
||||
|
@ -2155,9 +2125,7 @@ static AstNode *ast_parse_extern_decl(ParseContext *pc, size_t *token_index, boo
|
|||
/*
|
||||
UseDecl = "use" Expression ";"
|
||||
*/
|
||||
static AstNode *ast_parse_use(ParseContext *pc, size_t *token_index,
|
||||
ZigList<AstNode*> *directives, VisibMod visib_mod)
|
||||
{
|
||||
static AstNode *ast_parse_use(ParseContext *pc, size_t *token_index, VisibMod visib_mod) {
|
||||
Token *use_kw = &pc->tokens->at(*token_index);
|
||||
if (use_kw->id != TokenIdKeywordUse)
|
||||
return nullptr;
|
||||
|
@ -2165,7 +2133,6 @@ static AstNode *ast_parse_use(ParseContext *pc, size_t *token_index,
|
|||
|
||||
AstNode *node = ast_create_node(pc, NodeTypeUse, use_kw);
|
||||
node->data.use.top_level_decl.visib_mod = visib_mod;
|
||||
node->data.use.top_level_decl.directives = directives;
|
||||
node->data.use.expr = ast_parse_expression(pc, token_index, true);
|
||||
|
||||
ast_eat_token(pc, token_index, TokenIdSemicolon);
|
||||
|
@ -2175,13 +2142,11 @@ static AstNode *ast_parse_use(ParseContext *pc, size_t *token_index,
|
|||
}
|
||||
|
||||
/*
|
||||
ContainerDecl = ("struct" | "enum" | "union") "Symbol" option(ParamDeclList) "{" many(StructMember) "}"
|
||||
StructMember = many(Directive) option(VisibleMod) (StructField | FnDef | GlobalVarDecl | ContainerDecl)
|
||||
StructField : "Symbol" option(":" Expression) ",")
|
||||
ContainerDecl = ("struct" | "enum" | "union") Symbol option(ParamDeclList) "{" many(StructMember) "}"
|
||||
StructMember = (StructField | FnDef | GlobalVarDecl | ContainerDecl)
|
||||
StructField = Symbol option(":" Expression) ",")
|
||||
*/
|
||||
static AstNode *ast_parse_container_decl(ParseContext *pc, size_t *token_index,
|
||||
ZigList<AstNode*> *directives, VisibMod visib_mod)
|
||||
{
|
||||
static AstNode *ast_parse_container_decl(ParseContext *pc, size_t *token_index, VisibMod visib_mod) {
|
||||
Token *first_token = &pc->tokens->at(*token_index);
|
||||
|
||||
ContainerKind kind;
|
||||
|
@ -2203,7 +2168,6 @@ static AstNode *ast_parse_container_decl(ParseContext *pc, size_t *token_index,
|
|||
node->data.struct_decl.kind = kind;
|
||||
node->data.struct_decl.name = token_buf(struct_name);
|
||||
node->data.struct_decl.top_level_decl.visib_mod = visib_mod;
|
||||
node->data.struct_decl.top_level_decl.directives = directives;
|
||||
|
||||
Token *paren_or_brace = &pc->tokens->at(*token_index);
|
||||
if (paren_or_brace->id == TokenIdLParen) {
|
||||
|
@ -2217,10 +2181,6 @@ static AstNode *ast_parse_container_decl(ParseContext *pc, size_t *token_index,
|
|||
}
|
||||
|
||||
for (;;) {
|
||||
Token *directive_token = &pc->tokens->at(*token_index);
|
||||
ZigList<AstNode *> *directive_list = allocate<ZigList<AstNode*>>(1);
|
||||
ast_parse_directives(pc, token_index, directive_list);
|
||||
|
||||
Token *visib_tok = &pc->tokens->at(*token_index);
|
||||
VisibMod visib_mod;
|
||||
if (visib_tok->id == TokenIdKeywordPub) {
|
||||
|
@ -2233,20 +2193,20 @@ static AstNode *ast_parse_container_decl(ParseContext *pc, size_t *token_index,
|
|||
visib_mod = VisibModPrivate;
|
||||
}
|
||||
|
||||
AstNode *fn_def_node = ast_parse_fn_def(pc, token_index, false, directive_list, visib_mod);
|
||||
AstNode *fn_def_node = ast_parse_fn_def(pc, token_index, false, visib_mod);
|
||||
if (fn_def_node) {
|
||||
node->data.struct_decl.decls.append(fn_def_node);
|
||||
continue;
|
||||
}
|
||||
|
||||
AstNode *var_decl_node = ast_parse_variable_declaration_expr(pc, token_index, false, directive_list, visib_mod);
|
||||
AstNode *var_decl_node = ast_parse_variable_declaration_expr(pc, token_index, false, visib_mod);
|
||||
if (var_decl_node) {
|
||||
ast_eat_token(pc, token_index, TokenIdSemicolon);
|
||||
node->data.struct_decl.decls.append(var_decl_node);
|
||||
continue;
|
||||
}
|
||||
|
||||
AstNode *container_decl_node = ast_parse_container_decl(pc, token_index, directive_list, visib_mod);
|
||||
AstNode *container_decl_node = ast_parse_container_decl(pc, token_index, visib_mod);
|
||||
if (container_decl_node) {
|
||||
node->data.struct_decl.decls.append(container_decl_node);
|
||||
continue;
|
||||
|
@ -2255,10 +2215,6 @@ static AstNode *ast_parse_container_decl(ParseContext *pc, size_t *token_index,
|
|||
Token *token = &pc->tokens->at(*token_index);
|
||||
|
||||
if (token->id == TokenIdRBrace) {
|
||||
if (directive_list->length > 0) {
|
||||
ast_error(pc, directive_token, "invalid directive");
|
||||
}
|
||||
|
||||
*token_index += 1;
|
||||
break;
|
||||
} else if (token->id == TokenIdSymbol) {
|
||||
|
@ -2266,7 +2222,6 @@ static AstNode *ast_parse_container_decl(ParseContext *pc, size_t *token_index,
|
|||
*token_index += 1;
|
||||
|
||||
field_node->data.struct_field.top_level_decl.visib_mod = visib_mod;
|
||||
field_node->data.struct_field.top_level_decl.directives = directive_list;
|
||||
field_node->data.struct_field.name = token_buf(token);
|
||||
|
||||
Token *expr_or_comma = &pc->tokens->at(*token_index);
|
||||
|
@ -2293,9 +2248,7 @@ static AstNode *ast_parse_container_decl(ParseContext *pc, size_t *token_index,
|
|||
/*
|
||||
ErrorValueDecl : "error" "Symbol" ";"
|
||||
*/
|
||||
static AstNode *ast_parse_error_value_decl(ParseContext *pc, size_t *token_index,
|
||||
ZigList<AstNode*> *directives, VisibMod visib_mod)
|
||||
{
|
||||
static AstNode *ast_parse_error_value_decl(ParseContext *pc, size_t *token_index, VisibMod visib_mod) {
|
||||
Token *first_token = &pc->tokens->at(*token_index);
|
||||
|
||||
if (first_token->id != TokenIdKeywordError) {
|
||||
|
@ -2308,7 +2261,6 @@ static AstNode *ast_parse_error_value_decl(ParseContext *pc, size_t *token_index
|
|||
|
||||
AstNode *node = ast_create_node(pc, NodeTypeErrorValueDecl, first_token);
|
||||
node->data.error_value_decl.top_level_decl.visib_mod = visib_mod;
|
||||
node->data.error_value_decl.top_level_decl.directives = directives;
|
||||
node->data.error_value_decl.name = token_buf(name_tok);
|
||||
|
||||
normalize_parent_ptrs(node);
|
||||
|
@ -2318,9 +2270,7 @@ static AstNode *ast_parse_error_value_decl(ParseContext *pc, size_t *token_index
|
|||
/*
|
||||
TypeDecl = "type" "Symbol" "=" TypeExpr ";"
|
||||
*/
|
||||
static AstNode *ast_parse_type_decl(ParseContext *pc, size_t *token_index,
|
||||
ZigList<AstNode*> *directives, VisibMod visib_mod)
|
||||
{
|
||||
static AstNode *ast_parse_type_decl(ParseContext *pc, size_t *token_index, VisibMod visib_mod) {
|
||||
Token *first_token = &pc->tokens->at(*token_index);
|
||||
|
||||
if (first_token->id != TokenIdKeywordType) {
|
||||
|
@ -2338,21 +2288,17 @@ static AstNode *ast_parse_type_decl(ParseContext *pc, size_t *token_index,
|
|||
ast_eat_token(pc, token_index, TokenIdSemicolon);
|
||||
|
||||
node->data.type_decl.top_level_decl.visib_mod = visib_mod;
|
||||
node->data.type_decl.top_level_decl.directives = directives;
|
||||
|
||||
normalize_parent_ptrs(node);
|
||||
return node;
|
||||
}
|
||||
|
||||
/*
|
||||
TopLevelDecl = many(Directive) option(VisibleMod) (FnDef | ExternDecl | Import | ContainerDecl | GlobalVarDecl | ErrorValueDecl | CImportDecl | TypeDecl)
|
||||
TopLevelItem = ErrorValueDecl | Block | TopLevelDecl
|
||||
TopLevelDecl = option(VisibleMod) (FnDef | ExternDecl | ContainerDecl | GlobalVarDecl | TypeDecl | UseDecl)
|
||||
*/
|
||||
static void ast_parse_top_level_decls(ParseContext *pc, size_t *token_index, ZigList<AstNode *> *top_level_decls) {
|
||||
for (;;) {
|
||||
Token *directive_token = &pc->tokens->at(*token_index);
|
||||
ZigList<AstNode *> *directives = allocate<ZigList<AstNode*>>(1);
|
||||
ast_parse_directives(pc, token_index, directives);
|
||||
|
||||
Token *visib_tok = &pc->tokens->at(*token_index);
|
||||
VisibMod visib_mod;
|
||||
if (visib_tok->id == TokenIdKeywordPub) {
|
||||
|
@ -2365,61 +2311,56 @@ static void ast_parse_top_level_decls(ParseContext *pc, size_t *token_index, Zig
|
|||
visib_mod = VisibModPrivate;
|
||||
}
|
||||
|
||||
AstNode *fn_def_node = ast_parse_fn_def(pc, token_index, false, directives, visib_mod);
|
||||
AstNode *fn_def_node = ast_parse_fn_def(pc, token_index, false, visib_mod);
|
||||
if (fn_def_node) {
|
||||
top_level_decls->append(fn_def_node);
|
||||
continue;
|
||||
}
|
||||
|
||||
AstNode *fn_proto_node = ast_parse_extern_decl(pc, token_index, false, directives, visib_mod);
|
||||
AstNode *fn_proto_node = ast_parse_extern_decl(pc, token_index, false, visib_mod);
|
||||
if (fn_proto_node) {
|
||||
top_level_decls->append(fn_proto_node);
|
||||
continue;
|
||||
}
|
||||
|
||||
AstNode *use_node = ast_parse_use(pc, token_index, directives, visib_mod);
|
||||
AstNode *use_node = ast_parse_use(pc, token_index, visib_mod);
|
||||
if (use_node) {
|
||||
top_level_decls->append(use_node);
|
||||
continue;
|
||||
}
|
||||
|
||||
AstNode *struct_node = ast_parse_container_decl(pc, token_index, directives, visib_mod);
|
||||
AstNode *struct_node = ast_parse_container_decl(pc, token_index, visib_mod);
|
||||
if (struct_node) {
|
||||
top_level_decls->append(struct_node);
|
||||
continue;
|
||||
}
|
||||
|
||||
AstNode *var_decl_node = ast_parse_variable_declaration_expr(pc, token_index, false,
|
||||
directives, visib_mod);
|
||||
AstNode *var_decl_node = ast_parse_variable_declaration_expr(pc, token_index, false, visib_mod);
|
||||
if (var_decl_node) {
|
||||
ast_eat_token(pc, token_index, TokenIdSemicolon);
|
||||
top_level_decls->append(var_decl_node);
|
||||
continue;
|
||||
}
|
||||
|
||||
AstNode *error_value_node = ast_parse_error_value_decl(pc, token_index, directives, visib_mod);
|
||||
AstNode *error_value_node = ast_parse_error_value_decl(pc, token_index, visib_mod);
|
||||
if (error_value_node) {
|
||||
top_level_decls->append(error_value_node);
|
||||
continue;
|
||||
}
|
||||
|
||||
AstNode *type_decl_node = ast_parse_type_decl(pc, token_index, directives, visib_mod);
|
||||
AstNode *type_decl_node = ast_parse_type_decl(pc, token_index, visib_mod);
|
||||
if (type_decl_node) {
|
||||
top_level_decls->append(type_decl_node);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (directives->length > 0) {
|
||||
ast_error(pc, directive_token, "invalid directive");
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
zig_unreachable();
|
||||
}
|
||||
|
||||
/*
|
||||
Root : many(TopLevelDecl) token(EOF)
|
||||
Root = many(TopLevelItem) "EOF"
|
||||
*/
|
||||
static AstNode *ast_parse_root(ParseContext *pc, size_t *token_index) {
|
||||
AstNode *node = ast_create_node(pc, NodeTypeRoot, &pc->tokens->at(*token_index));
|
||||
|
@ -2471,7 +2412,6 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont
|
|||
break;
|
||||
case NodeTypeFnProto:
|
||||
visit_field(&node->data.fn_proto.return_type, visit, context);
|
||||
visit_node_list(node->data.fn_proto.top_level_decl.directives, visit, context);
|
||||
visit_node_list(&node->data.fn_proto.params, visit, context);
|
||||
break;
|
||||
case NodeTypeFnDef:
|
||||
|
@ -2487,9 +2427,6 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont
|
|||
case NodeTypeBlock:
|
||||
visit_node_list(&node->data.block.statements, visit, context);
|
||||
break;
|
||||
case NodeTypeDirective:
|
||||
visit_field(&node->data.directive.expr, visit, context);
|
||||
break;
|
||||
case NodeTypeReturnExpr:
|
||||
visit_field(&node->data.return_expr.expr, visit, context);
|
||||
break;
|
||||
|
@ -2497,12 +2434,10 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont
|
|||
visit_field(&node->data.defer.expr, visit, context);
|
||||
break;
|
||||
case NodeTypeVariableDeclaration:
|
||||
visit_node_list(node->data.variable_declaration.top_level_decl.directives, visit, context);
|
||||
visit_field(&node->data.variable_declaration.type, visit, context);
|
||||
visit_field(&node->data.variable_declaration.expr, visit, context);
|
||||
break;
|
||||
case NodeTypeTypeDecl:
|
||||
visit_node_list(node->data.type_decl.top_level_decl.directives, visit, context);
|
||||
visit_field(&node->data.type_decl.child_type, visit, context);
|
||||
break;
|
||||
case NodeTypeErrorValueDecl:
|
||||
|
@ -2550,7 +2485,6 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont
|
|||
break;
|
||||
case NodeTypeUse:
|
||||
visit_field(&node->data.use.expr, visit, context);
|
||||
visit_node_list(node->data.use.top_level_decl.directives, visit, context);
|
||||
break;
|
||||
case NodeTypeBoolLiteral:
|
||||
// none
|
||||
|
@ -2626,11 +2560,9 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont
|
|||
case NodeTypeContainerDecl:
|
||||
visit_node_list(&node->data.struct_decl.fields, visit, context);
|
||||
visit_node_list(&node->data.struct_decl.decls, visit, context);
|
||||
visit_node_list(node->data.struct_decl.top_level_decl.directives, visit, context);
|
||||
break;
|
||||
case NodeTypeStructField:
|
||||
visit_field(&node->data.struct_field.type, visit, context);
|
||||
visit_node_list(node->data.struct_field.top_level_decl.directives, visit, context);
|
||||
break;
|
||||
case NodeTypeContainerInitExpr:
|
||||
visit_field(&node->data.container_init_expr.type, visit, context);
|
||||
|
@ -2688,16 +2620,6 @@ static void clone_subtree_list_omit_inline_params(ZigList<AstNode *> *dest, ZigL
|
|||
}
|
||||
}
|
||||
|
||||
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_special(AstNode **dest, AstNode *src, uint32_t *next_node_index,
|
||||
enum AstCloneSpecial special)
|
||||
{
|
||||
|
@ -2713,10 +2635,6 @@ static void clone_subtree_field(AstNode **dest, AstNode *src, uint32_t *next_nod
|
|||
return clone_subtree_field_special(dest, src, next_node_index, AstCloneSpecialNone);
|
||||
}
|
||||
|
||||
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_special(AstNode *old_node, uint32_t *next_node_index, enum AstCloneSpecial special) {
|
||||
AstNode *new_node = allocate_nonzero<AstNode>(1);
|
||||
safe_memcpy(new_node, old_node, 1);
|
||||
|
@ -2730,8 +2648,6 @@ AstNode *ast_clone_subtree_special(AstNode *old_node, uint32_t *next_node_index,
|
|||
&old_node->data.root.top_level_decls, next_node_index);
|
||||
break;
|
||||
case NodeTypeFnProto:
|
||||
clone_subtree_tld(&new_node->data.fn_proto.top_level_decl, &old_node->data.fn_proto.top_level_decl,
|
||||
next_node_index);
|
||||
clone_subtree_field(&new_node->data.fn_proto.return_type, old_node->data.fn_proto.return_type,
|
||||
next_node_index);
|
||||
|
||||
|
@ -2761,9 +2677,6 @@ AstNode *ast_clone_subtree_special(AstNode *old_node, uint32_t *next_node_index,
|
|||
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;
|
||||
|
@ -2771,14 +2684,10 @@ AstNode *ast_clone_subtree_special(AstNode *old_node, uint32_t *next_node_index,
|
|||
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:
|
||||
|
@ -2832,8 +2741,6 @@ AstNode *ast_clone_subtree_special(AstNode *old_node, uint32_t *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
|
||||
|
@ -2908,13 +2815,9 @@ AstNode *ast_clone_subtree_special(AstNode *old_node, uint32_t *next_node_index,
|
|||
next_node_index);
|
||||
clone_subtree_list(&new_node->data.struct_decl.decls, &old_node->data.struct_decl.decls,
|
||||
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);
|
||||
|
|
|
@ -109,6 +109,7 @@ struct ZigKeyword {
|
|||
static const struct ZigKeyword zig_keywords[] = {
|
||||
{"asm", TokenIdKeywordAsm},
|
||||
{"break", TokenIdKeywordBreak},
|
||||
{"coldcc", TokenIdKeywordColdCC},
|
||||
{"const", TokenIdKeywordConst},
|
||||
{"continue", TokenIdKeywordContinue},
|
||||
{"defer", TokenIdKeywordDefer},
|
||||
|
@ -123,6 +124,7 @@ static const struct ZigKeyword zig_keywords[] = {
|
|||
{"goto", TokenIdKeywordGoto},
|
||||
{"if", TokenIdKeywordIf},
|
||||
{"inline", TokenIdKeywordInline},
|
||||
{"nakedcc", TokenIdKeywordNakedCC},
|
||||
{"noalias", TokenIdKeywordNoAlias},
|
||||
{"null", TokenIdKeywordNull},
|
||||
{"pub", TokenIdKeywordPub},
|
||||
|
@ -1476,6 +1478,8 @@ const char * token_name(TokenId id) {
|
|||
case TokenIdKeywordType: return "type";
|
||||
case TokenIdKeywordInline: return "inline";
|
||||
case TokenIdKeywordDefer: return "defer";
|
||||
case TokenIdKeywordColdCC: return "coldcc";
|
||||
case TokenIdKeywordNakedCC: return "nakedcc";
|
||||
case TokenIdLParen: return "(";
|
||||
case TokenIdRParen: return ")";
|
||||
case TokenIdComma: return ",";
|
||||
|
|
|
@ -46,6 +46,8 @@ enum TokenId {
|
|||
TokenIdKeywordInline,
|
||||
TokenIdKeywordDefer,
|
||||
TokenIdKeywordThis,
|
||||
TokenIdKeywordColdCC,
|
||||
TokenIdKeywordNakedCC,
|
||||
TokenIdLParen,
|
||||
TokenIdRParen,
|
||||
TokenIdComma,
|
||||
|
|
|
@ -13,9 +13,9 @@ const want_main_symbol = !want_start_symbol;
|
|||
var argc: usize = undefined;
|
||||
var argv: &&u8 = undefined;
|
||||
|
||||
#attribute("naked")
|
||||
#condition(want_start_symbol)
|
||||
export fn _start() -> unreachable {
|
||||
export nakedcc fn _start() -> unreachable {
|
||||
@setFnVisible(this, want_start_symbol);
|
||||
|
||||
switch (@compileVar("arch")) {
|
||||
x86_64 => {
|
||||
argc = asm("mov (%%rsp), %[argc]": [argc] "=r" (-> usize));
|
||||
|
@ -44,8 +44,9 @@ fn callMainAndExit() -> unreachable {
|
|||
linux.exit(0);
|
||||
}
|
||||
|
||||
#condition(want_main_symbol)
|
||||
export fn main(c_argc: i32, c_argv: &&u8) -> i32 {
|
||||
@setFnVisible(this, want_main_symbol);
|
||||
|
||||
argc = usize(c_argc);
|
||||
argv = c_argv;
|
||||
callMain() %% return 1;
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
// These functions are provided when not linking against libc because LLVM
|
||||
// sometimes generates code that calls them.
|
||||
|
||||
#debug_safety(false)
|
||||
export fn memset(dest: &u8, c: u8, n: usize) -> &u8 {
|
||||
@setDebugSafety(this, false);
|
||||
|
||||
var index: usize = 0;
|
||||
while (index != n) {
|
||||
dest[index] = c;
|
||||
|
@ -11,8 +12,9 @@ export fn memset(dest: &u8, c: u8, n: usize) -> &u8 {
|
|||
return dest;
|
||||
}
|
||||
|
||||
#debug_safety(false)
|
||||
export fn memcpy(noalias dest: &u8, noalias src: &const u8, n: usize) -> &u8 {
|
||||
@setDebugSafety(this, false);
|
||||
|
||||
var index: usize = 0;
|
||||
while (index != n) {
|
||||
dest[index] = src[index];
|
||||
|
|
|
@ -8,18 +8,19 @@ const udwords = [2]su_int;
|
|||
const low = if (@compileVar("is_big_endian")) 1 else 0;
|
||||
const high = 1 - low;
|
||||
|
||||
#debug_safety(false)
|
||||
export fn __udivdi3(a: du_int, b: du_int) -> du_int {
|
||||
@setDebugSafety(this, false);
|
||||
return __udivmoddi4(a, b, null);
|
||||
}
|
||||
|
||||
#debug_safety(false)
|
||||
fn du_int_to_udwords(x: du_int) -> udwords {
|
||||
@setDebugSafety(this, false);
|
||||
return *(&udwords)(&x);
|
||||
}
|
||||
|
||||
#debug_safety(false)
|
||||
export fn __udivmoddi4(a: du_int, b: du_int, maybe_rem: ?&du_int) -> du_int {
|
||||
@setDebugSafety(this, false);
|
||||
|
||||
const n_uword_bits = @sizeOf(su_int) * CHAR_BIT;
|
||||
const n_udword_bits = @sizeOf(du_int) * CHAR_BIT;
|
||||
var n = du_int_to_udwords(a);
|
||||
|
@ -203,15 +204,17 @@ export fn __udivmoddi4(a: du_int, b: du_int, maybe_rem: ?&du_int) -> du_int {
|
|||
return *(&du_int)(&q[0]);
|
||||
}
|
||||
|
||||
#debug_safety(false)
|
||||
export fn __umoddi3(a: du_int, b: du_int) -> du_int {
|
||||
@setDebugSafety(this, false);
|
||||
|
||||
var r: du_int = undefined;
|
||||
__udivmoddi4(a, b, &r);
|
||||
return r;
|
||||
}
|
||||
|
||||
#attribute("test")
|
||||
fn test_umoddi3() {
|
||||
@setFnTest(this, true);
|
||||
|
||||
test_one_umoddi3(0, 1, 0);
|
||||
test_one_umoddi3(2, 1, 0);
|
||||
test_one_umoddi3(0x8000000000000000, 1, 0x0);
|
||||
|
@ -224,8 +227,9 @@ fn test_one_umoddi3(a: du_int, b: du_int, expected_r: du_int) {
|
|||
assert(r == expected_r);
|
||||
}
|
||||
|
||||
#attribute("test")
|
||||
fn test_udivmoddi4() {
|
||||
@setFnTest(this, true);
|
||||
|
||||
const cases = [][4]du_int {
|
||||
[]du_int{0x0000000000000000, 0x0000000000000001, 0x0000000000000000, 0x0000000000000000},
|
||||
[]du_int{0x0000000080000000, 0x0000000100000001, 0x0000000000000000, 0x0000000080000000},
|
||||
|
|
|
@ -126,8 +126,9 @@ pub struct CBuf {
|
|||
}
|
||||
}
|
||||
|
||||
#attribute("test")
|
||||
fn testSimpleCBuf() {
|
||||
@setFnTest(this, true);
|
||||
|
||||
var buf = %%CBuf.initEmpty(&debug.global_allocator);
|
||||
assert(buf.len() == 0);
|
||||
%%buf.appendCStr(c"hello");
|
||||
|
@ -146,12 +147,14 @@ fn testSimpleCBuf() {
|
|||
assert(buf.startsWithCBuf(&buf2));
|
||||
}
|
||||
|
||||
#attribute("test")
|
||||
fn testCompileTimeStrCmp() {
|
||||
@setFnTest(this, true);
|
||||
|
||||
assert(@constEval(cmp(c"aoeu", c"aoez") == -1));
|
||||
}
|
||||
|
||||
#attribute("test")
|
||||
fn testCompileTimeStrLen() {
|
||||
@setFnTest(this, true);
|
||||
|
||||
assert(@constEval(len(c"123456789") == 9));
|
||||
}
|
||||
|
|
|
@ -230,8 +230,9 @@ pub struct SmallHashMap(K: type, V: type, hash: fn(key: K)->u32, eql: fn(a: K, b
|
|||
}
|
||||
}
|
||||
|
||||
#attribute("test")
|
||||
fn basicHashMapTest() {
|
||||
@setFnTest(this, true);
|
||||
|
||||
var map: HashMap(i32, i32, hash_i32, eql_i32) = undefined;
|
||||
map.init(&debug.global_allocator);
|
||||
defer map.deinit();
|
||||
|
|
|
@ -423,8 +423,9 @@ fn bufPrintUnsigned(inline T: type, out_buf: []u8, x: T) -> usize {
|
|||
return len;
|
||||
}
|
||||
|
||||
#attribute("test")
|
||||
fn parseU64DigitTooBig() {
|
||||
@setFnTest(this, true);
|
||||
|
||||
parseUnsigned(u64, "123a", 10) %% |err| {
|
||||
if (err == error.InvalidChar) return;
|
||||
@unreachable();
|
||||
|
|
|
@ -49,8 +49,9 @@ pub struct List(T: type) {
|
|||
}
|
||||
}
|
||||
|
||||
#attribute("test")
|
||||
fn basicListTest() {
|
||||
@setFnTest(this, true);
|
||||
|
||||
var list = List(i32).init(&debug.global_allocator);
|
||||
defer list.deinit();
|
||||
|
||||
|
|
|
@ -77,8 +77,8 @@ pub fn sliceAsInt(buf: []u8, is_be: bool, inline T: type) -> T {
|
|||
return result;
|
||||
}
|
||||
|
||||
#attribute("test")
|
||||
fn testSliceAsInt() {
|
||||
@setFnTest(this, true);
|
||||
{
|
||||
const buf = []u8{0x00, 0x00, 0x12, 0x34};
|
||||
const answer = sliceAsInt(buf[0...], true, u64);
|
||||
|
|
12
std/net.zig
12
std/net.zig
|
@ -180,8 +180,9 @@ error Overflow;
|
|||
error JunkAtEnd;
|
||||
error Incomplete;
|
||||
|
||||
#static_eval_enable(false)
|
||||
fn parseIp6(buf: []const u8) -> %Address {
|
||||
@setFnStaticEval(this, false);
|
||||
|
||||
var result: Address = undefined;
|
||||
result.family = linux.AF_INET6;
|
||||
result.scope_id = 0;
|
||||
|
@ -318,8 +319,9 @@ fn parseIp4(buf: []const u8) -> %u32 {
|
|||
}
|
||||
|
||||
|
||||
#attribute("test")
|
||||
fn testParseIp4() {
|
||||
@setFnTest(this, true);
|
||||
|
||||
assert(%%parseIp4("127.0.0.1") == endian.swapIfLe(u32, 0x7f000001));
|
||||
switch (parseIp4("256.0.0.1")) { Overflow => {}, else => @unreachable(), }
|
||||
switch (parseIp4("x.0.0.1")) { InvalidChar => {}, else => @unreachable(), }
|
||||
|
@ -328,8 +330,9 @@ fn testParseIp4() {
|
|||
switch (parseIp4("100..0.1")) { InvalidChar => {}, else => @unreachable(), }
|
||||
}
|
||||
|
||||
#attribute("test")
|
||||
fn testParseIp6() {
|
||||
@setFnTest(this, true);
|
||||
|
||||
{
|
||||
const addr = %%parseIp6("FF01:0:0:0:0:0:0:FB");
|
||||
assert(addr.addr[0] == 0xff);
|
||||
|
@ -338,8 +341,9 @@ fn testParseIp6() {
|
|||
}
|
||||
}
|
||||
|
||||
#attribute("test")
|
||||
fn testLookupSimpleIp() {
|
||||
@setFnTest(this, true);
|
||||
|
||||
{
|
||||
var addrs_buf: [5]Address = undefined;
|
||||
const addrs = %%lookup("192.168.1.1", addrs_buf);
|
||||
|
|
|
@ -27,8 +27,7 @@ pub fn getRandomBytes(buf: []u8) -> %void {
|
|||
}
|
||||
}
|
||||
|
||||
#attribute("cold")
|
||||
pub fn abort() -> unreachable {
|
||||
pub coldcc fn abort() -> unreachable {
|
||||
switch (@compileVar("os")) {
|
||||
linux, darwin => {
|
||||
system.raise(system.SIGABRT);
|
||||
|
|
|
@ -153,8 +153,9 @@ struct MersenneTwister(
|
|||
}
|
||||
}
|
||||
|
||||
#attribute("test")
|
||||
fn testFloat32() {
|
||||
@setFnTest(this, true);
|
||||
|
||||
var r: Rand = undefined;
|
||||
r.init(42);
|
||||
|
||||
|
@ -165,8 +166,9 @@ fn testFloat32() {
|
|||
}}
|
||||
}
|
||||
|
||||
#attribute("test")
|
||||
fn testMT19937_64() {
|
||||
@setFnTest(this, true);
|
||||
|
||||
var rng: MT19937_64 = undefined;
|
||||
rng.init(rand_test.mt64_seed);
|
||||
for (rand_test.mt64_data) |value| {
|
||||
|
@ -174,8 +176,9 @@ fn testMT19937_64() {
|
|||
}
|
||||
}
|
||||
|
||||
#attribute("test")
|
||||
fn testMT19937_32() {
|
||||
@setFnTest(this, true);
|
||||
|
||||
var rng: MT19937_32 = undefined;
|
||||
rng.init(rand_test.mt32_seed);
|
||||
for (rand_test.mt32_data) |value| {
|
||||
|
|
|
@ -12,8 +12,9 @@ pub fn sliceEql(inline T: type, a: []const T, b: []const T) -> bool {
|
|||
return true;
|
||||
}
|
||||
|
||||
#attribute("test")
|
||||
fn stringEquality() {
|
||||
fn testStringEquality() {
|
||||
@setFnTest(this, true);
|
||||
|
||||
assert(eql("abcd", "abcd"));
|
||||
assert(!eql("abcdef", "abZdef"));
|
||||
assert(!eql("abcdefg", "abcdef"));
|
||||
|
|
|
@ -2,8 +2,9 @@ const assert = @import("std").debug.assert;
|
|||
|
||||
var argv: &&const u8 = undefined;
|
||||
|
||||
#attribute("test")
|
||||
fn constSliceChild() {
|
||||
@setFnTest(this, true);
|
||||
|
||||
const strs = ([]&const u8) {
|
||||
c"one",
|
||||
c"two",
|
||||
|
@ -13,16 +14,18 @@ fn constSliceChild() {
|
|||
bar(strs.len);
|
||||
}
|
||||
|
||||
#static_eval_enable(false)
|
||||
fn foo(args: [][]const u8) {
|
||||
@setFnStaticEval(this, false);
|
||||
|
||||
assert(args.len == 3);
|
||||
assert(streql(args[0], "one"));
|
||||
assert(streql(args[1], "two"));
|
||||
assert(streql(args[2], "three"));
|
||||
}
|
||||
|
||||
#static_eval_enable(false)
|
||||
fn bar(argc: usize) {
|
||||
@setFnStaticEval(this, false);
|
||||
|
||||
var args: [argc][]u8 = undefined;
|
||||
for (args) |_, i| {
|
||||
const ptr = argv[i];
|
||||
|
@ -31,15 +34,17 @@ fn bar(argc: usize) {
|
|||
foo(args);
|
||||
}
|
||||
|
||||
#static_eval_enable(false)
|
||||
fn strlen(ptr: &const u8) -> usize {
|
||||
@setFnStaticEval(this, false);
|
||||
|
||||
var count: usize = 0;
|
||||
while (ptr[count] != 0; count += 1) {}
|
||||
return count;
|
||||
}
|
||||
|
||||
#static_eval_enable(false)
|
||||
fn streql(a: []const u8, b: []const u8) -> bool {
|
||||
@setFnStaticEval(this, false);
|
||||
|
||||
if (a.len != b.len) return false;
|
||||
for (a) |item, index| {
|
||||
if (b[index] != item) return false;
|
||||
|
|
|
@ -8,17 +8,24 @@ enum Number {
|
|||
Four,
|
||||
}
|
||||
|
||||
#attribute("test")
|
||||
fn enumToInt() {
|
||||
shouldEqual(Number.Zero, 0);
|
||||
shouldEqual(Number.One, 1);
|
||||
shouldEqual(Number.Two, 2);
|
||||
shouldEqual(Number.Three, 3);
|
||||
shouldEqual(Number.Four, 4);
|
||||
@setFnTest(this, true);
|
||||
|
||||
shouldEqual(false, Number.Zero, 0);
|
||||
shouldEqual(false, Number.One, 1);
|
||||
shouldEqual(false, Number.Two, 2);
|
||||
shouldEqual(false, Number.Three, 3);
|
||||
shouldEqual(false, Number.Four, 4);
|
||||
|
||||
shouldEqual(true, Number.Zero, 0);
|
||||
shouldEqual(true, Number.One, 1);
|
||||
shouldEqual(true, Number.Two, 2);
|
||||
shouldEqual(true, Number.Three, 3);
|
||||
shouldEqual(true, Number.Four, 4);
|
||||
}
|
||||
|
||||
// TODO add test with this disabled
|
||||
#static_eval_enable(false)
|
||||
fn shouldEqual(n: Number, expected: usize) {
|
||||
fn shouldEqual(inline static_eval: bool, n: Number, expected: usize) {
|
||||
@setFnStaticEval(this, static_eval);
|
||||
|
||||
assert(usize(n) == expected);
|
||||
}
|
||||
|
|
|
@ -15,8 +15,9 @@ enum ET {
|
|||
}
|
||||
}
|
||||
|
||||
#attribute("test")
|
||||
fn enumWithMembers() {
|
||||
@setFnTest(this, true);
|
||||
|
||||
const a = ET.SINT { -42 };
|
||||
const b = ET.UINT { 42 };
|
||||
var buf: [20]u8 = undefined;
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
const assert = @import("std").debug.assert;
|
||||
|
||||
#attribute("test")
|
||||
fn maxValueType() {
|
||||
@setFnTest(this, true);
|
||||
|
||||
// If the type of @maxValue(i32) was i32 then this implicit cast to
|
||||
// u32 would not work. But since the value is a number literal,
|
||||
// it works fine.
|
||||
|
|
|
@ -1,15 +1,17 @@
|
|||
const assert = @import("std").debug.assert;
|
||||
|
||||
#attribute("test")
|
||||
fn maybeReturn() {
|
||||
@setFnTest(this, true);
|
||||
|
||||
assert(??foo(1235));
|
||||
assert(if (const _ ?= foo(null)) false else true);
|
||||
assert(!??foo(1234));
|
||||
}
|
||||
|
||||
// TODO add another function with static_eval_enable(true)
|
||||
#static_eval_enable(false)
|
||||
// TODO test static eval maybe return
|
||||
fn foo(x: ?i32) -> ?bool {
|
||||
@setFnStaticEval(this, false);
|
||||
|
||||
const value = ?return x;
|
||||
return value > 1234;
|
||||
}
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
const assert = @import("std").debug.assert;
|
||||
|
||||
#attribute("test")
|
||||
fn namespaceDependsOnCompileVar() {
|
||||
@setFnTest(this, true);
|
||||
|
||||
if (some_namespace.a_bool) {
|
||||
assert(some_namespace.a_bool);
|
||||
} else {
|
||||
|
|
|
@ -1,16 +1,18 @@
|
|||
const assert = @import("std").debug.assert;
|
||||
const other = @import("other.zig");
|
||||
|
||||
#attribute("test")
|
||||
fn pubEnum() {
|
||||
@setFnTest(this, true);
|
||||
|
||||
pubEnumTest(other.APubEnum.Two);
|
||||
}
|
||||
fn pubEnumTest(foo: other.APubEnum) {
|
||||
assert(foo == other.APubEnum.Two);
|
||||
}
|
||||
|
||||
#attribute("test")
|
||||
fn castWithImportedSymbol() {
|
||||
@setFnTest(this, true);
|
||||
|
||||
assert(other.size_t(42) == 42);
|
||||
}
|
||||
|
||||
|
|
|
@ -10,8 +10,9 @@ pub struct SmallList(inline T: type, inline STATIC_SIZE: usize) {
|
|||
prealloc_items: [STATIC_SIZE]T,
|
||||
}
|
||||
|
||||
#attribute("test")
|
||||
fn functionWithReturnTypeType() {
|
||||
@setFnTest(this, true);
|
||||
|
||||
var list: List(i32) = undefined;
|
||||
var list2: List(i32) = undefined;
|
||||
list.length = 10;
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
const assert = @import("std").debug.assert;
|
||||
|
||||
#attribute("test")
|
||||
fn sizeofAndTypeOf() {
|
||||
@setFnTest(this, true);
|
||||
|
||||
const y: @typeOf(x) = 120;
|
||||
assert(@sizeOf(@typeOf(y)) == 2);
|
||||
}
|
||||
|
|
|
@ -5,8 +5,9 @@ struct Node {
|
|||
children: []Node,
|
||||
}
|
||||
|
||||
#attribute("test")
|
||||
fn structContainsSliceOfItself() {
|
||||
@setFnTest(this, true);
|
||||
|
||||
var nodes = []Node {
|
||||
Node {
|
||||
.payload = 1,
|
||||
|
|
|
@ -14,16 +14,18 @@ enum FormValue {
|
|||
Other: bool,
|
||||
}
|
||||
|
||||
#static_eval_enable(false)
|
||||
fn doThing(form_id: u64) -> %FormValue {
|
||||
@setFnStaticEval(this, false);
|
||||
|
||||
return switch (form_id) {
|
||||
17 => FormValue.Address { %return readOnce() },
|
||||
else => error.InvalidDebugInfo,
|
||||
}
|
||||
}
|
||||
|
||||
#attribute("test")
|
||||
fn switchProngReturnsErrorEnum() {
|
||||
@setFnTest(this, true);
|
||||
|
||||
%%doThing(17);
|
||||
assert(read_count == 1);
|
||||
}
|
||||
|
|
|
@ -7,8 +7,9 @@ enum FormValue {
|
|||
|
||||
error Whatever;
|
||||
|
||||
#static_eval_enable(false)
|
||||
fn foo(id: u64) -> %FormValue {
|
||||
@setFnStaticEval(this, false);
|
||||
|
||||
switch (id) {
|
||||
2 => FormValue.Two { true },
|
||||
1 => FormValue.One,
|
||||
|
@ -16,8 +17,9 @@ fn foo(id: u64) -> %FormValue {
|
|||
}
|
||||
}
|
||||
|
||||
#attribute("test")
|
||||
fn switchProngImplicitCast() {
|
||||
@setFnTest(this, true);
|
||||
|
||||
const result = switch (%%foo(2)) {
|
||||
One => false,
|
||||
Two => |x| x,
|
||||
|
|
|
@ -25,13 +25,15 @@ fn factorial(x: i32) -> i32 {
|
|||
}
|
||||
}
|
||||
|
||||
#attribute("test")
|
||||
fn thisReferToModuleCallPrivateFn() {
|
||||
@setFnTest(this, true);
|
||||
|
||||
assert(module.add(1, 2) == 3);
|
||||
}
|
||||
|
||||
#attribute("test")
|
||||
fn thisReferToContainer() {
|
||||
@setFnTest(this, true);
|
||||
|
||||
var pt = Point(i32) {
|
||||
.x = 12,
|
||||
.y = 34,
|
||||
|
@ -41,7 +43,8 @@ fn thisReferToContainer() {
|
|||
assert(pt.y == 35);
|
||||
}
|
||||
|
||||
#attribute("test")
|
||||
fn thisReferToFn() {
|
||||
@setFnTest(this, true);
|
||||
|
||||
assert(factorial(5) == 120);
|
||||
}
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
const assert = @import("std").debug.assert;
|
||||
|
||||
#attribute("test")
|
||||
fn varParams() {
|
||||
@setFnTest(this, true);
|
||||
|
||||
assert(max_i32(12, 34) == 34);
|
||||
assert(max_f64(1.2, 3.4) == 3.4);
|
||||
|
||||
|
@ -21,12 +22,14 @@ fn max_f64(a: f64, b: f64) -> f64 {
|
|||
max(a, b)
|
||||
}
|
||||
|
||||
#static_eval_enable(false)
|
||||
fn max_i32_noeval(a: i32, b: i32) -> i32 {
|
||||
@setFnStaticEval(this, false);
|
||||
|
||||
max(a, b)
|
||||
}
|
||||
|
||||
#static_eval_enable(false)
|
||||
fn max_f64_noeval(a: f64, b: f64) -> f64 {
|
||||
@setFnStaticEval(this, false);
|
||||
|
||||
max(a, b)
|
||||
}
|
||||
|
|
|
@ -7,8 +7,9 @@ struct Foo {
|
|||
d: ?i32,
|
||||
}
|
||||
|
||||
#attribute("test")
|
||||
fn initializing_a_struct_with_zeroes() {
|
||||
@setFnTest(this, true);
|
||||
|
||||
const foo: Foo = zeroes;
|
||||
assert(foo.a == 0.0);
|
||||
assert(foo.b == 0);
|
||||
|
|
|
@ -279,8 +279,9 @@ pub fn bar_function() {
|
|||
)SOURCE");
|
||||
|
||||
add_source_file(tc, "other.zig", R"SOURCE(
|
||||
#static_eval_enable(false)
|
||||
pub fn foo_function() -> bool {
|
||||
@setFnStaticEval(this, false);
|
||||
|
||||
// this one conflicts with the one from foo
|
||||
return true;
|
||||
}
|
||||
|
@ -686,14 +687,6 @@ fn a() {}
|
|||
fn a() {}
|
||||
)SOURCE", 1, ".tmp_source.zig:3:1: error: redefinition of 'a'");
|
||||
|
||||
add_compile_fail_case("bad directive", R"SOURCE(
|
||||
#bogus1("")
|
||||
extern fn b();
|
||||
#bogus2("")
|
||||
fn a() {}
|
||||
)SOURCE", 2, ".tmp_source.zig:2:1: error: invalid directive: 'bogus1'",
|
||||
".tmp_source.zig:4:1: error: invalid directive: 'bogus2'");
|
||||
|
||||
add_compile_fail_case("unreachable with return", R"SOURCE(
|
||||
fn a() -> unreachable {return;}
|
||||
)SOURCE", 1, ".tmp_source.zig:2:24: error: expected type 'unreachable', got 'void'");
|
||||
|
@ -1280,8 +1273,11 @@ struct Foo {
|
|||
x: i32,
|
||||
}
|
||||
const a = get_it();
|
||||
#static_eval_enable(false)
|
||||
fn get_it() -> Foo { Foo {.x = 13} }
|
||||
fn get_it() -> Foo {
|
||||
@setFnStaticEval(this, false);
|
||||
Foo {.x = 13}
|
||||
}
|
||||
|
||||
)SOURCE", 1, ".tmp_source.zig:5:17: error: unable to evaluate constant expression");
|
||||
|
||||
add_compile_fail_case("undeclared identifier error should mark fn as impure", R"SOURCE(
|
||||
|
@ -1316,8 +1312,11 @@ fn foo() {
|
|||
else => 3,
|
||||
};
|
||||
}
|
||||
#static_eval_enable(false)
|
||||
fn bar() -> i32 { 2 }
|
||||
fn bar() -> i32 {
|
||||
@setFnStaticEval(this, false);
|
||||
2
|
||||
}
|
||||
|
||||
)SOURCE", 1, ".tmp_source.zig:3:15: error: unable to infer expression type");
|
||||
|
||||
add_compile_fail_case("atomic orderings of cmpxchg", R"SOURCE(
|
||||
|
@ -1458,7 +1457,6 @@ pub struct SmallList(inline T: type, inline STATIC_SIZE: usize) {
|
|||
prealloc_items: [STATIC_SIZE]T,
|
||||
}
|
||||
|
||||
#attribute("test")
|
||||
fn function_with_return_type_type() {
|
||||
var list: List(i32) = undefined;
|
||||
list.length = 10;
|
||||
|
@ -1623,12 +1621,15 @@ pub fn main(args: [][]u8) -> %void {
|
|||
const a = []i32{1, 2, 3, 4};
|
||||
baz(bar(a));
|
||||
}
|
||||
#static_eval_enable(false)
|
||||
fn bar(a: []i32) -> i32 {
|
||||
@setFnStaticEval(this, false);
|
||||
|
||||
a[4]
|
||||
}
|
||||
#static_eval_enable(false)
|
||||
fn baz(a: i32) {}
|
||||
fn baz(a: i32) {
|
||||
@setFnStaticEval(this, false);
|
||||
}
|
||||
|
||||
)SOURCE");
|
||||
|
||||
add_debug_safety_case("integer addition overflow", R"SOURCE(
|
||||
|
@ -1637,8 +1638,9 @@ pub fn main(args: [][]u8) -> %void {
|
|||
const x = add(65530, 10);
|
||||
if (x == 0) return error.Whatever;
|
||||
}
|
||||
#static_eval_enable(false)
|
||||
fn add(a: u16, b: u16) -> u16 {
|
||||
@setFnStaticEval(this, false);
|
||||
|
||||
a + b
|
||||
}
|
||||
)SOURCE");
|
||||
|
@ -1649,8 +1651,9 @@ pub fn main(args: [][]u8) -> %void {
|
|||
const x = sub(10, 20);
|
||||
if (x == 0) return error.Whatever;
|
||||
}
|
||||
#static_eval_enable(false)
|
||||
fn sub(a: u16, b: u16) -> u16 {
|
||||
@setFnStaticEval(this, false);
|
||||
|
||||
a - b
|
||||
}
|
||||
)SOURCE");
|
||||
|
@ -1661,8 +1664,9 @@ pub fn main(args: [][]u8) -> %void {
|
|||
const x = mul(300, 6000);
|
||||
if (x == 0) return error.Whatever;
|
||||
}
|
||||
#static_eval_enable(false)
|
||||
fn mul(a: u16, b: u16) -> u16 {
|
||||
@setFnStaticEval(this, false);
|
||||
|
||||
a * b
|
||||
}
|
||||
)SOURCE");
|
||||
|
@ -1673,8 +1677,9 @@ pub fn main(args: [][]u8) -> %void {
|
|||
const x = neg(-32768);
|
||||
if (x == 0) return error.Whatever;
|
||||
}
|
||||
#static_eval_enable(false)
|
||||
fn neg(a: i16) -> i16 {
|
||||
@setFnStaticEval(this, false);
|
||||
|
||||
-a
|
||||
}
|
||||
)SOURCE");
|
||||
|
@ -1685,8 +1690,9 @@ pub fn main(args: [][]u8) -> %void {
|
|||
const x = shl(-16385, 1);
|
||||
if (x == 0) return error.Whatever;
|
||||
}
|
||||
#static_eval_enable(false)
|
||||
fn shl(a: i16, b: i16) -> i16 {
|
||||
@setFnStaticEval(this, false);
|
||||
|
||||
a << b
|
||||
}
|
||||
)SOURCE");
|
||||
|
@ -1697,8 +1703,9 @@ pub fn main(args: [][]u8) -> %void {
|
|||
const x = shl(0b0010111111111111, 3);
|
||||
if (x == 0) return error.Whatever;
|
||||
}
|
||||
#static_eval_enable(false)
|
||||
fn shl(a: u16, b: u16) -> u16 {
|
||||
@setFnStaticEval(this, false);
|
||||
|
||||
a << b
|
||||
}
|
||||
)SOURCE");
|
||||
|
@ -1708,8 +1715,9 @@ error Whatever;
|
|||
pub fn main(args: [][]u8) -> %void {
|
||||
const x = div0(999, 0);
|
||||
}
|
||||
#static_eval_enable(false)
|
||||
fn div0(a: i32, b: i32) -> i32 {
|
||||
@setFnStaticEval(this, false);
|
||||
|
||||
a / b
|
||||
}
|
||||
)SOURCE");
|
||||
|
@ -1720,8 +1728,9 @@ pub fn main(args: [][]u8) -> %void {
|
|||
const x = divExact(10, 3);
|
||||
if (x == 0) return error.Whatever;
|
||||
}
|
||||
#static_eval_enable(false)
|
||||
fn divExact(a: i32, b: i32) -> i32 {
|
||||
@setFnStaticEval(this, false);
|
||||
|
||||
@divExact(a, b)
|
||||
}
|
||||
)SOURCE");
|
||||
|
@ -1732,8 +1741,9 @@ pub fn main(args: [][]u8) -> %void {
|
|||
const x = widenSlice([]u8{1, 2, 3, 4, 5});
|
||||
if (x.len == 0) return error.Whatever;
|
||||
}
|
||||
#static_eval_enable(false)
|
||||
fn widenSlice(slice: []u8) -> []i32 {
|
||||
@setFnStaticEval(this, false);
|
||||
|
||||
([]i32)(slice)
|
||||
}
|
||||
)SOURCE");
|
||||
|
@ -1744,8 +1754,9 @@ pub fn main(args: [][]u8) -> %void {
|
|||
const x = shorten_cast(200);
|
||||
if (x == 0) return error.Whatever;
|
||||
}
|
||||
#static_eval_enable(false)
|
||||
fn shorten_cast(x: i32) -> i8 {
|
||||
@setFnStaticEval(this, false);
|
||||
|
||||
i8(x)
|
||||
}
|
||||
)SOURCE");
|
||||
|
@ -1756,8 +1767,9 @@ pub fn main(args: [][]u8) -> %void {
|
|||
const x = unsigned_cast(-10);
|
||||
if (x == 0) return error.Whatever;
|
||||
}
|
||||
#static_eval_enable(false)
|
||||
fn unsigned_cast(x: i32) -> u32 {
|
||||
@setFnStaticEval(this, false);
|
||||
|
||||
u32(x)
|
||||
}
|
||||
)SOURCE");
|
||||
|
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user