From b8880e32544679561e3543dfb6b8097abfc22565 Mon Sep 17 00:00:00 2001 From: Lindsey Kuper Date: Mon, 14 May 2012 16:55:01 -0700 Subject: [PATCH] Remove `be` keyword. Closes #2227. --- doc/rust.md | 2 +- src/librustsyntax/ast.rs | 1 - src/librustsyntax/fold.rs | 1 - src/librustsyntax/parse/classify.rs | 3 +-- src/librustsyntax/parse/lexer.rs | 8 +++--- src/librustsyntax/parse/parser.rs | 4 --- src/librustsyntax/print/pprust.rs | 25 +++++++++---------- src/librustsyntax/visit.rs | 1 - src/libstd/ufind.rs | 2 +- src/rustc/middle/borrowck.rs | 2 +- src/rustc/middle/check_loop.rs | 6 ----- src/rustc/middle/trans/base.rs | 10 -------- src/rustc/middle/trans/type_use.rs | 2 +- src/rustc/middle/tstate/ann.rs | 10 +++++--- .../middle/tstate/pre_post_conditions.rs | 5 ---- src/rustc/middle/tstate/states.rs | 8 ------ src/rustc/middle/ty.rs | 2 +- src/rustc/middle/typeck.rs | 9 ------- src/test/bench/99bob-tail.rs | 6 ++--- src/test/bench/shootout-fasta.rs | 4 +-- src/test/compile-fail/dead-code-be.rs | 9 ------- src/test/compile-fail/forgot-ret.rs | 2 +- src/test/compile-fail/tail-non-call.rs | 10 -------- src/test/compile-fail/tail-typeck.rs | 2 +- src/test/run-pass/tail-call-arg-leak.rs | 2 +- src/test/run-pass/tail-cps.rs | 4 +-- src/test/run-pass/tail-direct.rs | 4 +-- 27 files changed, 40 insertions(+), 104 deletions(-) delete mode 100644 src/test/compile-fail/dead-code-be.rs delete mode 100644 src/test/compile-fail/tail-non-call.rs diff --git a/doc/rust.md b/doc/rust.md index d7e35d8339f..3366a60de9b 100644 --- a/doc/rust.md +++ b/doc/rust.md @@ -210,7 +210,7 @@ The keywords in [source files](#source-files) are the following strings: ~~~~~~~~ {.keyword} alt assert -be break +break check claim class const cont copy crust do else enum export diff --git a/src/librustsyntax/ast.rs b/src/librustsyntax/ast.rs index 8c27b8ba989..f91a3151def 100644 --- a/src/librustsyntax/ast.rs +++ b/src/librustsyntax/ast.rs @@ -336,7 +336,6 @@ enum expr_ { expr_break, expr_cont, expr_ret(option<@expr>), - expr_be(@expr), expr_log(int, @expr, @expr), expr_new(/* arena */ @expr, diff --git a/src/librustsyntax/fold.rs b/src/librustsyntax/fold.rs index bc1cec9021e..4a91dbd3628 100644 --- a/src/librustsyntax/fold.rs +++ b/src/librustsyntax/fold.rs @@ -488,7 +488,6 @@ fn noop_fold_expr(e: expr_, fld: ast_fold) -> expr_ { expr_fail(e) { expr_fail(option::map(e, fld.fold_expr)) } expr_break | expr_cont { e } expr_ret(e) { expr_ret(option::map(e, fld.fold_expr)) } - expr_be(e) { expr_be(fld.fold_expr(e)) } expr_log(i, lv, e) { expr_log(i, fld.fold_expr(lv), fld.fold_expr(e)) } expr_assert(e) { expr_assert(fld.fold_expr(e)) } diff --git a/src/librustsyntax/parse/classify.rs b/src/librustsyntax/parse/classify.rs index 70f89a38f47..471fe15788d 100644 --- a/src/librustsyntax/parse/classify.rs +++ b/src/librustsyntax/parse/classify.rs @@ -42,7 +42,6 @@ fn need_parens(expr: @ast::expr, outer_prec: uint) -> bool { ast::expr_swap(_, _) { true } ast::expr_assign_op(_, _, _) { true } ast::expr_ret(_) { true } - ast::expr_be(_) { true } ast::expr_assert(_) { true } ast::expr_check(_, _) { true } ast::expr_log(_, _, _) { true } @@ -55,7 +54,7 @@ fn ends_in_lit_int(ex: @ast::expr) -> bool { ast::expr_lit(@{node: ast::lit_int(_, ast::ty_i), _}) { true } ast::expr_binary(_, _, sub) | ast::expr_unary(_, sub) | ast::expr_move(_, sub) | ast::expr_copy(sub) | - ast::expr_assign(_, sub) | ast::expr_be(sub) | + ast::expr_assign(_, sub) | ast::expr_assign_op(_, _, sub) | ast::expr_swap(_, sub) | ast::expr_log(_, _, sub) | ast::expr_assert(sub) | ast::expr_check(_, sub) { ends_in_lit_int(sub) } diff --git a/src/librustsyntax/parse/lexer.rs b/src/librustsyntax/parse/lexer.rs index ec9f785db2f..debdd3d57eb 100644 --- a/src/librustsyntax/parse/lexer.rs +++ b/src/librustsyntax/parse/lexer.rs @@ -104,7 +104,7 @@ fn is_bin_digit(c: char) -> bool { ret c == '0' || c == '1'; } fn consume_whitespace_and_comments(rdr: reader) { while is_whitespace(rdr.curr) { rdr.bump(); } - be consume_any_line_comment(rdr); + ret consume_any_line_comment(rdr); } fn consume_any_line_comment(rdr: reader) { @@ -114,9 +114,9 @@ fn consume_any_line_comment(rdr: reader) { while rdr.curr != '\n' && !rdr.is_eof() { rdr.bump(); } // Restart whitespace munch. - be consume_whitespace_and_comments(rdr); + ret consume_whitespace_and_comments(rdr); } - '*' { rdr.bump(); rdr.bump(); be consume_block_comment(rdr); } + '*' { rdr.bump(); rdr.bump(); ret consume_block_comment(rdr); } _ { ret; } } } @@ -140,7 +140,7 @@ fn consume_block_comment(rdr: reader) { } // restart whitespace munch. - be consume_whitespace_and_comments(rdr); + ret consume_whitespace_and_comments(rdr); } fn scan_exponent(rdr: reader) -> option { diff --git a/src/librustsyntax/parse/parser.rs b/src/librustsyntax/parse/parser.rs index 7c1e3a85a29..eb25660b45f 100644 --- a/src/librustsyntax/parse/parser.rs +++ b/src/librustsyntax/parse/parser.rs @@ -825,10 +825,6 @@ fn parse_bottom_expr(p: parser) -> pexpr { } else if eat_keyword(p, "cont") { ex = expr_cont; hi = p.span.hi; - } else if eat_keyword(p, "be") { - let e = parse_expr(p); - hi = e.span.hi; - ex = expr_be(e); } else if eat_keyword(p, "copy") { let e = parse_expr(p); ex = expr_copy(e); diff --git a/src/librustsyntax/print/pprust.rs b/src/librustsyntax/print/pprust.rs index 5f1f2323b60..70e3ec33c62 100644 --- a/src/librustsyntax/print/pprust.rs +++ b/src/librustsyntax/print/pprust.rs @@ -80,24 +80,24 @@ fn print_crate_(s: ps, &&crate: @ast::crate) { eof(s.s); } -fn ty_to_str(ty: @ast::ty) -> str { be to_str(ty, print_type); } +fn ty_to_str(ty: @ast::ty) -> str { ret to_str(ty, print_type); } -fn pat_to_str(pat: @ast::pat) -> str { be to_str(pat, print_pat); } +fn pat_to_str(pat: @ast::pat) -> str { ret to_str(pat, print_pat); } -fn expr_to_str(e: @ast::expr) -> str { be to_str(e, print_expr); } +fn expr_to_str(e: @ast::expr) -> str { ret to_str(e, print_expr); } -fn stmt_to_str(s: ast::stmt) -> str { be to_str(s, print_stmt); } +fn stmt_to_str(s: ast::stmt) -> str { ret to_str(s, print_stmt); } -fn item_to_str(i: @ast::item) -> str { be to_str(i, print_item); } +fn item_to_str(i: @ast::item) -> str { ret to_str(i, print_item); } -fn attr_to_str(i: ast::attribute) -> str { be to_str(i, print_attribute); } +fn attr_to_str(i: ast::attribute) -> str { ret to_str(i, print_attribute); } fn typarams_to_str(tps: [ast::ty_param]) -> str { - be to_str(tps, print_type_params) + ret to_str(tps, print_type_params) } fn path_to_str(&&p: @ast::path) -> str { - be to_str(p, bind print_path(_, _, false)); + ret to_str(p, bind print_path(_, _, false)); } fn fun_to_str(decl: ast::fn_decl, name: ast::ident, @@ -174,11 +174,11 @@ fn meta_item_to_str(mi: ast::meta_item) -> str { } fn attribute_to_str(attr: ast::attribute) -> str { - be to_str(attr, print_attribute); + ret to_str(attr, print_attribute); } fn variant_to_str(var: ast::variant) -> str { - be to_str(var, print_variant); + ret to_str(var, print_variant); } #[test] @@ -1102,7 +1102,6 @@ fn print_expr(s: ps, &&expr: @ast::expr) { _ { } } } - ast::expr_be(result) { word_nbsp(s, "be"); print_expr(s, result); } ast::expr_log(lvl, lexp, expr) { alt check lvl { 1 { word_nbsp(s, "log"); print_expr(s, expr); } @@ -1149,7 +1148,7 @@ fn print_expr_parens_if_not_bot(s: ps, ex: @ast::expr) { ast::expr_fail(_) | ast::expr_ret(_) | ast::expr_binary(_, _, _) | ast::expr_unary(_, _) | ast::expr_move(_, _) | ast::expr_copy(_) | - ast::expr_assign(_, _) | ast::expr_be(_) | + ast::expr_assign(_, _) | ast::expr_assign_op(_, _, _) | ast::expr_swap(_, _) | ast::expr_log(_, _, _) | ast::expr_assert(_) | ast::expr_call(_, _, true) | @@ -1623,7 +1622,7 @@ fn print_literal(s: ps, &&lit: @ast::lit) { } } -fn lit_to_str(l: @ast::lit) -> str { be to_str(l, print_literal); } +fn lit_to_str(l: @ast::lit) -> str { ret to_str(l, print_literal); } fn next_lit(s: ps, pos: uint) -> option { alt s.literals { diff --git a/src/librustsyntax/visit.rs b/src/librustsyntax/visit.rs index 980f9244c35..2a926c1fa9d 100644 --- a/src/librustsyntax/visit.rs +++ b/src/librustsyntax/visit.rs @@ -422,7 +422,6 @@ fn visit_expr(ex: @expr, e: E, v: vt) { expr_break { } expr_cont { } expr_ret(eo) { visit_expr_opt(eo, e, v); } - expr_be(x) { v.visit_expr(x, e, v); } expr_log(_, lv, x) { v.visit_expr(lv, e, v); v.visit_expr(x, e, v); diff --git a/src/libstd/ufind.rs b/src/libstd/ufind.rs index 555c0a0f212..9a7483553dc 100644 --- a/src/libstd/ufind.rs +++ b/src/libstd/ufind.rs @@ -28,7 +28,7 @@ fn grow(ufnd: ufind, n: uint) { fn find(ufnd: ufind, n: uint) -> uint { alt ufnd.nodes[n] { none { ret n; } - some(m) { let m_ = m; be find(ufnd, m_); } + some(m) { let m_ = m; ret find(ufnd, m_); } } } diff --git a/src/rustc/middle/borrowck.rs b/src/rustc/middle/borrowck.rs index cd881f1c731..ed310495813 100644 --- a/src/rustc/middle/borrowck.rs +++ b/src/rustc/middle/borrowck.rs @@ -972,7 +972,7 @@ impl categorize_methods for borrowck_ctxt { ast::expr_swap(*) | ast::expr_move(*) | ast::expr_assign(*) | ast::expr_assign_op(*) | ast::expr_fn(*) | ast::expr_fn_block(*) | ast::expr_assert(*) | ast::expr_check(*) | ast::expr_ret(*) | - ast::expr_be(*) | ast::expr_loop_body(*) | ast::expr_unary(*) | + ast::expr_loop_body(*) | ast::expr_unary(*) | ast::expr_copy(*) | ast::expr_cast(*) | ast::expr_fail(*) | ast::expr_vstore(*) | ast::expr_vec(*) | ast::expr_tup(*) | ast::expr_if_check(*) | ast::expr_if(*) | ast::expr_log(*) | diff --git a/src/rustc/middle/check_loop.rs b/src/rustc/middle/check_loop.rs index b815afd3646..098ec82ac0a 100644 --- a/src/rustc/middle/check_loop.rs +++ b/src/rustc/middle/check_loop.rs @@ -44,12 +44,6 @@ fn check_crate(tcx: ty::ctxt, crate: @crate) { } visit::visit_expr_opt(oe, cx, v); } - expr_be(re) { - if !cx.can_ret { - tcx.sess.span_err(e.span, "`be` in block function"); - } - v.visit_expr(re, cx, v); - } _ { visit::visit_expr(e, cx, v); } } } diff --git a/src/rustc/middle/trans/base.rs b/src/rustc/middle/trans/base.rs index 9ef307e3ea7..cec6f197da8 100644 --- a/src/rustc/middle/trans/base.rs +++ b/src/rustc/middle/trans/base.rs @@ -3267,9 +3267,6 @@ fn trans_expr(bcx: block, e: @ast::expr, dest: dest) -> block { assert dest == ignore; ret trans_ret(bcx, ex); } - ast::expr_be(ex) { - ret trans_be(bcx, ex); - } ast::expr_fail(expr) { assert dest == ignore; ret trans_fail_expr(bcx, some(e.span), expr); @@ -3641,13 +3638,6 @@ fn build_return(bcx: block) { Br(bcx, bcx.fcx.llreturn); } -fn trans_be(cx: block, e: @ast::expr) -> block { - // FIXME: Turn this into a real tail call once - // calling convention issues are settled - let _icx = cx.insn_ctxt("trans_be"); - ret trans_ret(cx, some(e)); -} - fn init_local(bcx: block, local: @ast::local) -> block { let _icx = bcx.insn_ctxt("init_local"); let ty = node_id_type(bcx, local.node.id); diff --git a/src/rustc/middle/trans/type_use.rs b/src/rustc/middle/trans/type_use.rs index 65cc2a949b5..38b0bd08697 100644 --- a/src/rustc/middle/trans/type_use.rs +++ b/src/rustc/middle/trans/type_use.rs @@ -172,7 +172,7 @@ fn mark_for_expr(cx: ctx, e: @expr) { } } expr_assign(val, _) | expr_swap(val, _) | expr_assign_op(_, val, _) | - expr_ret(some(val)) | expr_be(val) { + expr_ret(some(val)) { node_type_needs(cx, use_repr, val.id); } expr_index(base, _) | expr_field(base, _, _) { diff --git a/src/rustc/middle/tstate/ann.rs b/src/rustc/middle/tstate/ann.rs index 82388f9b89f..ab8c921a008 100644 --- a/src/rustc/middle/tstate/ann.rs +++ b/src/rustc/middle/tstate/ann.rs @@ -41,13 +41,15 @@ type pre_and_post_state = {prestate: prestate, poststate: poststate}; type ts_ann = @{conditions: pre_and_post, states: pre_and_post_state}; -fn true_precond(num_vars: uint) -> precond { be create_tritv(num_vars); } +fn true_precond(num_vars: uint) -> precond { ret create_tritv(num_vars); } -fn true_postcond(num_vars: uint) -> postcond { be true_precond(num_vars); } +fn true_postcond(num_vars: uint) -> postcond { ret true_precond(num_vars); } -fn empty_prestate(num_vars: uint) -> prestate { be true_precond(num_vars); } +fn empty_prestate(num_vars: uint) -> prestate { ret true_precond(num_vars); } -fn empty_poststate(num_vars: uint) -> poststate { be true_precond(num_vars); } +fn empty_poststate(num_vars: uint) -> poststate { + ret true_precond(num_vars); +} fn false_postcond(num_vars: uint) -> postcond { let rslt = create_tritv(num_vars); diff --git a/src/rustc/middle/tstate/pre_post_conditions.rs b/src/rustc/middle/tstate/pre_post_conditions.rs index e5bcec7a46c..7b8c864580d 100644 --- a/src/rustc/middle/tstate/pre_post_conditions.rs +++ b/src/rustc/middle/tstate/pre_post_conditions.rs @@ -391,11 +391,6 @@ fn find_pre_post_expr(fcx: fn_ctxt, e: @expr) { } } } - expr_be(val) { - find_pre_post_expr(fcx, val); - set_pre_and_post(fcx.ccx, e.id, expr_prestate(fcx.ccx, val), - false_postcond(num_local_vars)); - } expr_if(antec, conseq, maybe_alt) { join_then_else(fcx, antec, conseq, maybe_alt, e.id, plain_if); } diff --git a/src/rustc/middle/tstate/states.rs b/src/rustc/middle/tstate/states.rs index 8fbdec3d9b5..4e484fccd07 100644 --- a/src/rustc/middle/tstate/states.rs +++ b/src/rustc/middle/tstate/states.rs @@ -483,14 +483,6 @@ fn find_pre_post_state_expr(fcx: fn_ctxt, pres: prestate, e: @expr) -> bool { } ret changed; } - expr_be(val) { - let mut changed = set_prestate_ann(fcx.ccx, e.id, pres); - let post = false_postcond(num_constrs); - // except for the "diverges" bit... - kill_poststate_(fcx, fcx.enclosing.i_diverge, post); - set_poststate_ann(fcx.ccx, e.id, post); - ret changed | find_pre_post_state_expr(fcx, pres, val); - } expr_if(antec, conseq, maybe_alt) { ret join_then_else(fcx, antec, conseq, maybe_alt, e.id, plain_if, pres); diff --git a/src/rustc/middle/ty.rs b/src/rustc/middle/ty.rs index d6f59279028..09a1ef7c4c3 100644 --- a/src/rustc/middle/ty.rs +++ b/src/rustc/middle/ty.rs @@ -1456,7 +1456,7 @@ fn is_instantiable(cx: ctxt, r_ty: t) -> bool { ty_box(mt) | ty_uniq(mt) | ty_rptr(_, mt) { - be type_requires(cx, seen, r_ty, mt.ty); + ret type_requires(cx, seen, r_ty, mt.ty); } ty_ptr(mt) { diff --git a/src/rustc/middle/typeck.rs b/src/rustc/middle/typeck.rs index 8d897161678..6f9b767a870 100644 --- a/src/rustc/middle/typeck.rs +++ b/src/rustc/middle/typeck.rs @@ -3364,15 +3364,6 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, } fcx.write_bot(id); } - ast::expr_be(e) { - if !ast_util::is_call_expr(e) { - tcx.sess.span_err(expr.span, - "non-call expression in tail call"); - } - check_expr_with(fcx, e, fcx.ret_ty); - bot = true; - fcx.write_nil(id); - } ast::expr_log(_, lv, e) { bot = check_expr_with(fcx, lv, ty::mk_mach_uint(tcx, ast::ty_u32)); // Note: this does not always execute, so do not propagate bot: diff --git a/src/test/bench/99bob-tail.rs b/src/test/bench/99bob-tail.rs index f0f1daf331d..ccd6b6ca098 100644 --- a/src/test/bench/99bob-tail.rs +++ b/src/test/bench/99bob-tail.rs @@ -12,21 +12,21 @@ fn main() { #debug("Take one down and pass it around, %d \ bottles of beer on the wall.", n-1); #debug(""); - if n > 3 { be multiple(n - 1); } else { be dual(); } + if n > 3 { ret multiple(n - 1); } else { ret dual(); } } fn dual() { #debug("2 bottles of beer on the wall, 2 bottles of beer,"); #debug("Take one down and pass it around, \ 1 bottle of beer on the wall."); #debug(""); - be single(); + ret single(); } fn single() { #debug("1 bottle of beer on the wall, 1 bottle of beer,"); #debug("Take one down and pass it around, \ no more bottles of beer on the wall."); #debug(""); - be none(); + ret none(); } fn none() { #debug("No more bottles of beer on the wall, \ diff --git a/src/test/bench/shootout-fasta.rs b/src/test/bench/shootout-fasta.rs index 9b2fcadd2c5..bb1e4eab85c 100644 --- a/src/test/bench/shootout-fasta.rs +++ b/src/test/bench/shootout-fasta.rs @@ -35,8 +35,8 @@ fn select_random(r: u32, genelist: [aminoacids]) -> char { if hi > lo + 1u { let mid: uint = lo + (hi - lo) / 2u; if target < v[mid].prob { - be bisect(v, lo, mid, target); - } else { be bisect(v, mid, hi, target); } + ret bisect(v, lo, mid, target); + } else { ret bisect(v, mid, hi, target); } } else { ret v[hi].ch; } } ret bisect(genelist, 0u, vec::len::(genelist) - 1u, r); diff --git a/src/test/compile-fail/dead-code-be.rs b/src/test/compile-fail/dead-code-be.rs deleted file mode 100644 index bc7ec4491ee..00000000000 --- a/src/test/compile-fail/dead-code-be.rs +++ /dev/null @@ -1,9 +0,0 @@ -// xfail-test -// -*- rust -*- - -// error-pattern: dead - -fn f(caller: str) { log(debug, caller); } - -fn main() { be f("main"); #debug("Paul is dead"); } - diff --git a/src/test/compile-fail/forgot-ret.rs b/src/test/compile-fail/forgot-ret.rs index 4e422c970c6..4d78b7a7aff 100644 --- a/src/test/compile-fail/forgot-ret.rs +++ b/src/test/compile-fail/forgot-ret.rs @@ -1,7 +1,7 @@ // -*- rust -*- // error-pattern: not all control paths return a value -fn god_exists(a: int) -> bool { be god_exists(a); } +fn god_exists(a: int) -> bool { ret god_exists(a); } fn f(a: int) -> int { if god_exists(a) { ret 5; }; } diff --git a/src/test/compile-fail/tail-non-call.rs b/src/test/compile-fail/tail-non-call.rs deleted file mode 100644 index f2622bc4dfa..00000000000 --- a/src/test/compile-fail/tail-non-call.rs +++ /dev/null @@ -1,10 +0,0 @@ -// error-pattern:non-call expression in tail call - -fn f() -> int { - let x = 1; - be x; -} - -fn main() { - let y = f(); -} diff --git a/src/test/compile-fail/tail-typeck.rs b/src/test/compile-fail/tail-typeck.rs index c121458f233..0c64e9d9556 100644 --- a/src/test/compile-fail/tail-typeck.rs +++ b/src/test/compile-fail/tail-typeck.rs @@ -1,6 +1,6 @@ // error-pattern: mismatched types -fn f() -> int { be g(); } +fn f() -> int { ret g(); } fn g() -> uint { ret 0u; } diff --git a/src/test/run-pass/tail-call-arg-leak.rs b/src/test/run-pass/tail-call-arg-leak.rs index b208d32009d..269fa53211d 100644 --- a/src/test/run-pass/tail-call-arg-leak.rs +++ b/src/test/run-pass/tail-call-arg-leak.rs @@ -2,6 +2,6 @@ // use of tail calls causes arg slot leaks, issue #160. -fn inner(dummy: str, b: bool) { if b { be inner(dummy, false); } } +fn inner(dummy: str, b: bool) { if b { ret inner(dummy, false); } } fn main() { inner("hi", true); } diff --git a/src/test/run-pass/tail-cps.rs b/src/test/run-pass/tail-cps.rs index 725ac36fbc8..a5cb9c6f5fa 100644 --- a/src/test/run-pass/tail-cps.rs +++ b/src/test/run-pass/tail-cps.rs @@ -9,11 +9,11 @@ fn main() { let k = checktrue; evenk(42, k); oddk(45, k); } fn evenk(n: int, k: native fn(bool) -> bool) -> bool { #debug("evenk"); log(debug, n); - if n == 0 { be k(true); } else { be oddk(n - 1, k); } + if n == 0 { ret k(true); } else { ret oddk(n - 1, k); } } fn oddk(n: int, k: native fn(bool) -> bool) -> bool { #debug("oddk"); log(debug, n); - if n == 0 { be k(false); } else { be evenk(n - 1, k); } + if n == 0 { ret k(false); } else { ret evenk(n - 1, k); } } diff --git a/src/test/run-pass/tail-direct.rs b/src/test/run-pass/tail-direct.rs index 0bd771e7369..bfb0b19340e 100644 --- a/src/test/run-pass/tail-direct.rs +++ b/src/test/run-pass/tail-direct.rs @@ -4,6 +4,6 @@ // -*- rust -*- fn main() { assert (even(42)); assert (odd(45)); } -fn even(n: int) -> bool { if n == 0 { ret true; } else { be odd(n - 1); } } +fn even(n: int) -> bool { if n == 0 { ret true; } else { ret odd(n - 1); } } -fn odd(n: int) -> bool { if n == 0 { ret false; } else { be even(n - 1); } } +fn odd(n: int) -> bool { if n == 0 { ret false; } else { ret even(n - 1); } }