1 /** 2 * Copyright: Copyright (c) 2010-2011 Jacob Carlborg. 3 * Authors: Jacob Carlborg 4 * Version: Initial created: Jan 29, 2010 5 * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0) 6 */ 7 module mambo.util.Use; 8 9 import tango.core.Tuple; 10 import tango.core.Traits; 11 12 /** 13 * This struct can be used to implement, what looks similar to, new statements. This 14 * struct overloads the "in" operator which a delegate can be passed to. The delegate 15 * passed to the "in" operator will then be called at an appropriate time decided by the 16 * implementation of the function returning the Use struct. 17 * 18 * Examples: 19 * --- 20 * Use!(void delegate (), bool) unless (bool condition) 21 * { 22 * Use!(void delegate (), bool) use; 23 * use.args[1] = condition; 24 * 25 * use.args[0] = (void delegate () dg, bool condition) { 26 * if (!condition) 27 * dg(); 28 * }; 29 * 30 * return use; 31 * } 32 * 33 * int a = 3; 34 * int b = 4; 35 * 36 * unless(a == b) in { 37 * println("a != b"); 38 * }; 39 * --- 40 */ 41 struct Use (ARGS...) 42 { 43 static assert (ARGS.length > 0); 44 45 private 46 { 47 alias ReturnTypeOf!(ARGS[0]) ReturnType; 48 49 static if (ARGS.length >= 2) 50 alias Tuple!(ReturnType delegate (ARGS), ARGS[1 .. $]) NEW_ARGS; 51 52 else 53 alias Tuple!(ReturnType delegate (ARGS)) NEW_ARGS; 54 } 55 56 /** 57 * The first argument will be the delegate that performs some arbitrary operation. The 58 * rest of the arguments will be pass as arguments to the delegate in "args[0]". 59 */ 60 NEW_ARGS args; 61 62 /** 63 * Overloads the "in" operator. The given delegate is supplied by the user and will be 64 * called at a time the implementaion has decided. 65 * 66 * Params: 67 * dg = the user supplied delegate that will be called 68 * 69 * Returns: what ever the delegate stored in "args[0]" returns 70 */ 71 ReturnType opIn (ARGS[0] dg) 72 { 73 assert(args[0]); 74 75 static if (NEW_ARGS.length == 1) 76 return args[0](dg); 77 78 else 79 return args[0](dg, args[1 .. $]); 80 } 81 } 82 83 /** 84 * This is a helper struct used by the "restore" function. It overloads the "in" operator 85 * to allow to taking a delegate. 86 */ 87 struct RestoreStruct (U, T) 88 { 89 /// The delegate that performs the operation. 90 U delegate(U delegate (), ref T) dg; 91 92 /// A pointer to the value to pass to the delegate. 93 T* value; 94 95 /** 96 * Overloads the "in" operator. It will simply call the delegate stored in the struct 97 * passing in the given delegate and the value stored in the struct. 98 * 99 * Params: 100 * deleg = the delegate to pass the delegate stored in the struct 101 * 102 * Returns: whatever the delegate stored in the struct returns 103 * 104 * See_Also: restore 105 */ 106 U opIn (U delegate () deleg) 107 { 108 return dg(deleg, *value); 109 } 110 } 111 112 /** 113 * Restores the given variable to the value it was when it was passed to the function 114 * after the delegate has finished. 115 * 116 * Examples: 117 * --- 118 * int a = 3; 119 * 120 * restore(a) in { 121 * a = 4; 122 * } 123 * 124 * assert(a == 3); 125 * --- 126 * 127 * Params: 128 * val = variable that will be restored 129 * 130 * Returns: a RestoreStruct 131 * 132 * See_Also: RestoreStruct 133 */ 134 RestoreStruct!(U, T) restore (U = void, T) (ref T val) 135 { 136 RestoreStruct!(U, T) restoreStruct; 137 138 restoreStruct.dg = (U delegate () dg, ref T value){ 139 T t = value; 140 141 static if (is(U == void)) 142 { 143 dg(); 144 value = t; 145 } 146 147 else 148 { 149 auto result = dg(); 150 value = t; 151 152 return result; 153 } 154 }; 155 156 restoreStruct.value = &val; 157 158 return restoreStruct; 159 }