-- Copyright 1993-1998, by the Cecil Project -- Department of Computer Science and Engineering, University of Washington -- See the LICENSE file for license information. (--DOC abstract object bool isa hashable[bool]; -- hashable implies comparable concrete representation true isa bool; concrete representation false isa bool; The `bool' type is the type of boolean values. There are two constants of `bool' type, `true' and `false'. Boolean values are comparable and hashable, but more importantly they support a number of basic control structures: --) --DOCSKIP bool, true, and false are really predefined..... extend bool isa hashable[bool]; --DOCENDSKIP ---------- -- bool methods ---------- (--DOC `if' takes either one closure or two closure arguments, acting like an if-then or an if-then-else statement, as follows: if(i < j, { -- then statements }, { -- else statements }); The three-argument `if' control construct returns the value of the executed closure; i.e., if-then-else can be used as an expression, not just a statement. `if_false' negates the result of the test. One way to achieve the effect of an if-then-elseif-then-...-else construct is to use another `if' call as the body of the else; unfortunately, this tends to indent poorly. The `switch' construct indents better but may not run as fast. The compiler implementation nearly always implements `if' and `if_false' as efficiently as you'd expect in C, despite its source-level use of messages and closures. --) signature if(bool, tc:&():`T, fc:&():`T):T; method if_false(t@:bool, fc:&():`T, tc:&():`T):T (** control_strucutre **) { if(t, tc, fc) } method if(t@:bool, tc:&():void):void (** control_structure **) { if(t, tc, {}); } method if_false(t@:bool, fc:&():void):void (** control_strucutre **) { if(t, {}, fc); } method =(l@:bool, r@:bool):bool { l == r } (--DOC Other control structures on booleans include `&' (and), `|' (or), `not', and `=>' (implies). These control structures' second argument is either a boolean expression or a closure with boolean return type. When the second argument is not a closure, it is always evaluated. To achieve short-circuiting semantics, use closure arguments. For example: if(x != 0 & { y / x > 0 }, { ... }); --) signature |(bool, bool):bool; signature |(bool, &():bool):bool; precedence | left_associative; signature &(bool, bool):bool; signature &(bool, &():bool):bool; precedence & left_associative above |; signature not(bool):bool; method =>(l@:bool, r@:bool):bool { not(l) | r } method =>(l@:bool, r@closure:&():bool):bool { not(l) | r } precedence => non_associative below |; --DOC The `assert' method allows checks to be made in support of defensive --DOC programming. If the test expression evaluates to is `false', the --DOC program quits with an error message. The closure form is provided in --DOC case constructing the error message is expensive, and is --DOC short-circuited in the (expected) case where the test is true. method assert(b@:bool):void { assert(b, ""); } method assert(b@:bool, msg@:string):void (** inline **) { if_false(b, { assertion_failed(msg); }); } method assert(b@:bool, msg_closure@closure:&():string):void (** inline **) { if_false(b, { assertion_failed(eval(msg_closure)); }); } private method assertion_failed(msg:string):void (** no_inline **) { error("Assertion failed" || if(msg.non_empty, {": "}, {""}) || msg); } --DOC The `as_integer' method returns 0 for `false' and 1 for `true'. signature as_integer(bool):int; method hash(b@:bool, range:int):int { b.as_integer.hash(range) } ---------- -- true methods ---------- method if(@:true, tc:&():`T, fc:&():`T):T (** control_structure **) { eval(tc) } method |(@:true, @:bool):bool { true } method |(@:true, @closure:&():bool):bool { true } method &(@:true, r@:bool):bool { r } method &(@:true, r@closure:&():bool):bool (** control_structure **) { eval(r) } method not(@:true):bool { false } method as_integer(@:true):int { 1 } method print_string(@:true):string { "true" } ---------- -- false methods ---------- method if(@:false, tc:&():`T, fc:&():`T):T (** control_structure **) { eval(fc) } method |(@:false, r@:bool):bool { r } method |(@:false, r@closure:&():bool):bool (** control_structure **) { eval(r) } method &(@:false, @:bool):bool { false } method &(@:false, @closure:&():bool):bool { false } method not(@:false):bool { true } method as_integer(@:false):int { 0 } method print_string(@:false):string { "false" }