1 /**************************************************************************** 2 * Copyright (C) 2012 by Matteo Franchin * 3 * * 4 * This file is part of Box. * 5 * * 6 * Box is free software: you can redistribute it and/or modify it * 7 * under the terms of the GNU Lesser General Public License as published * 8 * by the Free Software Foundation, either version 3 of the License, or * 9 * (at your option) any later version. * 10 * * 11 * Box is distributed in the hope that it will be useful, * 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 14 * GNU Lesser General Public License for more details. * 15 * * 16 * You should have received a copy of the GNU Lesser General Public * 17 * License along with Box. If not, see <http://www.gnu.org/licenses/>. * 18 ****************************************************************************/ 19 20 /** 21 * @file callable.h 22 * @brief Declaration of BoxCallable and related functionality. 23 * 24 * This header defines the BoxCallable object, an abstraction for a callable 25 * entity in Box which may be implemented in either C or Box VM code and may 26 * have links to associated data (what - in other languages - is referred to 27 * as a closure). The callable object also contains details which allow 28 * generating Box VM code which calls the object. 29 */ 30 31 #ifndef _BOX_CALLABLE_H 32 # define _BOX_CALLABLE_H 33 34 # include <box/exception.h> 35 # include <box/types.h> 36 # include <box/obj.h> 37 # include <box/vm.h> 38 39 /** 40 * @brief Unique identifier. 41 * 42 * This is typically a string used to identify procedures. 43 */ 44 typedef char BoxUid; 45 46 /** 47 * First (and simplest) C implementation of a BoxCallable object: takes just a 48 * pointer to the parent. 49 * @param parent The pointer to the parent (object over which the callable 50 * operates). 51 * @return A BoxException object in case of errors, NULL otherwise. 52 */ 53 typedef BoxException *(*BoxCCall1)(BoxPtr *parent); 54 55 /** 56 * Second C implementation of a BoxCallable object: takes a pointer to the 57 * parent and a pointer to the child. 58 * @param parent The pointer to the parent. 59 * @param child The pointer to the child. 60 * @return A BoxException object in case of errors, NULL otherwise. 61 */ 62 typedef BoxException *(*BoxCCall2)(BoxPtr *parent, BoxPtr *child); 63 64 /** 65 * Third (and most complete) C implementation of a BoxCallable object: takes a 66 * pointer to the corresponding BoxCallable object (from which the callable 67 * context can be retrieved, thus implementing a closure), a pointer to the 68 * parent and a pointer to the child. 69 * @param callable The BoxCallable object corresponding to this function. This 70 * is typically what is returned by BoxCallable_Create_From_CCall3. 71 * @param parent The pointer to the parent. 72 * @param child The pointer to the child. 73 * @return A BoxException object in case of errors, NULL otherwise. 74 */ 75 typedef BoxException *(*BoxCCall3)(BoxPtr *callable, BoxPtr *parent, 76 BoxPtr *child); 77 78 /** 79 * Fourth C implementation of a BoxCallable object. This type is provided for 80 * compatibility with old code, where the C implementation is a function which 81 * takes just a pointer to the VM object. 82 * @param vm The calling VM. 83 * @return A BoxException object in case of errors, NULL otherwise. 84 */ 85 typedef BoxTask (*BoxCCallOld)(BoxVMX *vm); 86 87 /** 88 * @brief Abstraction of function in the Box language implementation. 89 * 90 * A @c BoxCallable object is an object which can be called by passing one 91 * parent and one child objects. The parent object is often the result of 92 * the call, while the child is typically the input argument. 93 * A @a BoxCallable object can be implemented as a C function or as a 94 * @c BoxVM procedure. 95 * 96 * @see BoxVM 97 */ 98 typedef struct BoxCallable_struct BoxCallable; 99 100 /** 101 * @brief Enumeration of the possible implementation for a @c BoxCallable 102 * object. 103 * 104 * @see BoxCallable 105 */ 106 typedef enum { 107 BOXCALLABLEKIND_UNDEFINED, /**< Undefined callable. */ 108 BOXCALLABLEKIND_C_1, /**< BoxCCall1. */ 109 BOXCALLABLEKIND_C_2, /**< BoxCCall2. */ 110 BOXCALLABLEKIND_C_3, /**< BoxCCall3. */ 111 BOXCALLABLEKIND_C_OLD, /**< BoxCCallOld. */ 112 BOXCALLABLEKIND_VM /**< VM call. */ 113 } BoxCallableKind; 114 115 /** 116 * Equivalent to #BoxSPtr_Link, but does type casting for #BoxCallable. 117 * @see BoxSPtr_Link 118 */ 119 #define BoxCallable_Link(t) ((BoxCallable *) BoxSPtr_Link(t)) 120 121 /** 122 * Equivalent to #BoxSPtr_Unlink, but does type casting for #BoxCallable. 123 * @see BoxSPtr_Unlink 124 */ 125 #define BoxCallable_Unlink(t) ((BoxCallable *) BoxSPtr_Unlink(t)) 126 127 /** 128 * @brief Create an undefined callable. 129 * 130 * The callable maps an object of type @p t_in to an object of type @p t_out. 131 * The object can be later defined using BoxCallable_Define_From_CCall1() and 132 * friends. 133 * @param t_out Type of the output object. 134 * @param t_in Type of the input object. 135 * @return A new #BoxCallable object. 136 */ 137 BOXEXPORT BOXOUT BoxCallable * 138 BoxCallable_Create_Undefined(BoxType *t_out, BoxType *t_in); 139 140 /** 141 * @brief Set the unique identifier for the callable. 142 * 143 * @param cb The callable. 144 * @brief uid A unique identifier for @p cb. 145 * @return Whether the operation succeeded. @c BOXBOOL_FALSE is returned if 146 * the uid has been already set. 147 */ 148 BOXEXPORT BoxBool 149 BoxCallable_Set_Uid(BoxCallable *cb, BoxUid *uid); 150 151 /** 152 * @brief Return the unique identifier associated to the given callable. 153 * 154 * @param cb The callable. 155 * @return Return the unique identifier (a #BoxUid object) for @p cb or @c NULL 156 * if @c cb does not have a unique identifier. 157 */ 158 BOXEXPORT BoxUid * 159 BoxCallable_Get_Uid(BoxCallable *cb); 160 161 /** 162 * Define a callable object from a BoxCCall1 C function. 163 * @param call The C function. 164 * @return BOXBOOL_TRUE on success, BOXBOOL_FALSE on failure. 165 */ 166 BOXEXPORT BOXOUT BoxCallable * 167 BoxCallable_Define_From_CCall1(BOXIN BoxCallable *cb, BoxCCall1 call); 168 169 /** 170 * Define a callable object from a BoxCCall2 C function. 171 * @param call The C function. 172 */ 173 BOXEXPORT BOXOUT BoxCallable * 174 BoxCallable_Define_From_CCall2(BOXIN BoxCallable *cb, BoxCCall2 call); 175 176 /** 177 * Define a callable object from old-style C function (BoxCCallOld). 178 */ 179 BOXEXPORT BOXOUT BoxCallable * 180 BoxCallable_Define_From_CCallOld(BOXIN BoxCallable *cb, BoxCCallOld call); 181 182 /** 183 * Create a callable object from a BoxVM procedure. 184 * @param t_out Output type for the callable. 185 * @param t_in Input type for the callable. 186 * @param context Pointer to additional data required by the callable. 187 * @param vm The VM which contains the callable implementation. 188 * @param num The call number for the callable implementation. 189 * @return A new callable which wraps the procedure `num' of the virtual 190 * machine `vm'. 191 */ 192 BOXEXPORT BOXOUT BoxCallable * 193 BoxCallable_Define_From_VM(BOXIN BoxCallable *cb, BoxVM *vm, BoxVMCallNum num); 194 195 /** 196 * @brief Return whether the callable is implemented. 197 * 198 * @param cb The callable. 199 * @return Whether the callable is implemented. 200 * @note A callable is implemented when it is 201 */ 202 BOXEXPORT BoxBool 203 BoxCallable_Is_Implemented(BoxCallable *cb); 204 205 /** 206 * @brief Return the call number for a VM callable. 207 * 208 * @param cb The input callable. 209 * @param vm The VM to which the call number refers to. 210 * @param cn Where to store the call number. 211 * @return If @p cb is a callable for a procedure defined in @p vm, then its 212 * call number is returned in <tt>*cn</tt> and @c BOXBOOL_TRUE is returned. 213 * In all the other cases, @c BOXBOOL_FALSE is returned. 214 */ 215 BOXEXPORT BoxBool 216 BoxCallable_Get_VM_Call_Num(BoxCallable *cb, BoxVM *vm, BoxVMCallNum *cn); 217 218 /** 219 * @brief Request a call number for a given callable. 220 * 221 * Request a call number (relative to the given virtual machine @p vm) for 222 * the given callable @p cb. A new callable is returned in <tt>*cb_out</tt> 223 * which references the new call number. Note that the call number is not 224 * allocated, if a valid call number is found in @p cb. For this reason, 225 * it is important to use the value returned in @p cb_out for subsequent calls 226 * to the function (as doing so will not generate new spurious call numbers). 227 * @param cb The callable for which a call number is requested. 228 * @param vm The virtual machine the call number should refer to. 229 * @param num Pointer to the location where the call number must be returned. 230 * @param cb_out Pointer to the location where a callable referencing the 231 * new call number should be stored. 232 * @return @c BOXBOOL_TRUE, if the function succeeded and @p num and @p cb_out 233 * were written with values, else @c BOXBOOL_FALSE. 234 */ 235 BOXEXPORT BoxBool 236 BoxCallable_Request_VM_Call_Num(BoxCallable *cb, BoxVM *vm, BoxVMCallNum *num, 237 BOXOUT BoxCallable **cb_out); 238 239 /** 240 * 241 */ 242 BOXEXPORT BoxException * 243 BoxCallable_Call1(BoxCallable *cb, BoxPtr *parent); 244 245 /** 246 * 247 */ 248 BOXEXPORT BoxException * 249 BoxCallable_Call2(BoxCallable *cb, BoxPtr *parent, BoxPtr *child); 250 251 BOXEXPORT BoxTask 252 BoxCallable_CallOld(BoxCallable *cb, BoxVMX *vmx); 253 254 #endif /* _BOX_CALLABLE_H */ 255