1Clownfish::Docs::WritinUgsCelrasCsoenst(r3i)buted Perl DColcouwmnefnitsaht:i:oDnocs::WritingClasses(3)
2
3
4

NAME

6       Clownfish::Docs::WritingClasses - Writing Apache Clownfish classes
7

DESCRIPTION

9   Parcels
10       Every Clownfish class belongs to a Clownfish parcel. Parcels are used
11       for namespacing and versioning. Information about parcels is stored in
12       ".cfp" files which contain a JSON hash with the following keys:
13
14name: The parcelXs name. It must contain only letters.
15
16nickname: A short nickname. It must contain only letters. This
17           nickname, followed by an underscore, is used to prefix generated C
18           symbols and macros. Depending on the kind of symbol, a lowercase or
19           uppercase prefix will be used.
20
21version: A version specifier of the following form (without
22           whitespace):
23
24               version-specifier = "v" version-number
25               version-number = digit+ | digit+ "." version-number
26
27prerequisites: A hash containing the prerequisite parcels. The hash
28           keys are the parcel names. The values contain the minimum required
29           version.
30
31       An example ".cfp" file might look like:
32
33           {
34               "name": "Pathfinder",
35               "nickname": "Pfind",
36               "version": "v2.3.8",
37               "prerequisites": {
38                   "Clownfish": "v0.6.3"
39               }
40           }
41
42       A parcel specifier of the following form is used in Clownfish header
43       files:
44
45           parcel-specifier = "parcel" parcel-name ";"
46           parcel-name = identifier
47
48       For example:
49
50           parcel Pathfinder;
51
52       Every ".cfh" file starts with a parcel specifier containing the name of
53       the parcel for all classes in the header file.
54
55       Initialization
56
57       Every Clownfish parcel must be initialized before it is used. The
58       initialization function is named "{parcel_nick}_bootstrap_parcel" and
59       takes no arguments.
60
61       Example call:
62
63           pfind_bootstrap_parcel();
64
65       The generated host language bindings call the bootstrap function
66       automatically. C projects must call the function manually.
67
68       Short names
69
70       If a macro with the uppercase name "{PARCEL_NICK}_USE_SHORT_NAMES" is
71       defined before including a generated C header, additional macros
72       without the parcel prefix will be defined for most symbols.
73
74       Example:
75
76           #define PFIND_USE_SHORT_NAMES
77           #include <Pathfinder/Graph.h>
78           #include <Pathfinder/Path.h>
79
80           /* Prefixes can be omitted. */
81           Path *path = Graph_Find_Shortest_Path(graph);
82
83           /* Without PFIND_USE_SHORT_NAMES, one would have to write: */
84           pfind_Path *path = PFIND_Graph_Find_Shortest_Path(graph);
85
86       For object types in Clownfish header files, prefixes of class structs
87       can also be omitted unless multiple parcels declare classes with the
88       same last component of the class name.
89
90       The XClownfishX parcel
91
92       The Clownfish runtime classes live in a parcel named "Clownfish" with
93       nickname "Cfish". Consequently, the short name macro is named
94       "CFISH_USE_SHORT_NAMES".
95
96   Declaring classes
97       Classes are declared in Clownfish header files using a declaration of
98       the following form:
99
100           class-declaration = class-exposure-specifier?
101                               class-modifier*
102                               "class" class-name
103                               ("nickname" class-nickname)?
104                               ("inherits" class-name)?
105                               "{" class-contents "}"
106           class-exposure-specifier = "public"
107           class-modifier = "inert" | "final"
108           class-name = identifier | identifier "::" class-name
109           class-nickname = identifier
110           class-contents = (variable-declaration | function-declaration)*
111
112       Class name components must start with an uppercase letter and must not
113       contain underscores. The last component must contain at least one
114       lowercase letter and must be unique for every class in a parcel.
115
116       For every class, a type with the name "{parcel_nick}_{Class_Last_Comp}"
117       is defined in the generated C header. This is an opaque typedef used to
118       ensure type safety.
119
120       For every class, a global variable with the uppercase name
121       "{PARCEL_NICK}_{CLASS_LAST_COMP}" is defined. This variable is a
122       pointer to a Clownfish::Class object which is initialized when
123       bootstrapping the parcel.
124
125       Non-inert classes inherit from Clownfish::Obj by default.
126
127       Example of a class declaration:
128
129           parcel Pathfinder;
130
131           public class Pathfinder::Graph::VisibilityGraph nickname VisGraph
132               extends Clownfish::Obj {
133               /* Variables and functions */
134           }
135
136       This will generate:
137
138           typedef struct pfind_VisibilityGraph pfind_VisibilityGraph;
139           extern cfish_Class *PFIND_VISIBILITYGRAPH;
140
141       Class exposure
142
143       API documentation will only be generated for classes with "public"
144       exposure.
145
146       Inert classes
147
148       Inert classes must contain only inert variables or inert functions,
149       that is, neither instance variables nor methods. They must not inherit
150       from another class nor be inherited from. TheyXre essentially nothing
151       more than a namespace for functions and global variables.
152
153       Final classes
154
155       For final classes, every method is made final, regardless of the method
156       modifier. Final classes must not be inherited from.
157
158   Variables
159       Variables are declared with a declaration of the following form:
160
161           variable-declaration = variable-modifier*
162                                  type variable-name ";"
163           variable-modifier = "inert"
164           variable-name = identifier
165
166       Inert variables
167
168       Inert variables are global class variables of which only a single copy
169       exists. They are declared in the generated C header with the name
170       "{parcel_nick}_{Class_Nick}_{Variable_Name}" and must be defined in a C
171       source file.
172
173       Example:
174
175           public class Pathfinder::Path {
176               public inert int max_path_length;
177           }
178
179       This will generate:
180
181           extern int pfind_Path_max_path_length;
182
183       The C source file defining the variable will typically use short names.
184       So the definition will look like:
185
186           int Path_max_path_length = 5000;
187
188       Instance variables
189
190       Non-inert variables are instance variables and added to the classXs
191       ivars struct.
192
193       Example:
194
195           public class Pathfinder::Path {
196               int num_nodes;
197
198               public int
199               Get_Num_Nodes(Path *self);
200           }
201
202       This will add a "num_nodes" member to the ivars struct of "Path".
203
204       The ivars struct
205
206       To access instance variables, the macro
207       "C_{PARCEL_NICK}_{CLASS_LAST_COMP}" must be defined before including
208       the generated header file. This will make a struct named
209       "{parcel_nick}_{Class_Name}IVARS" with a corresponding typedef and
210       short name available that contains all instance variables of the class
211       and all superclasses from the same parcel. Instance variables defined
212       in other parcels are not accessible. This is by design to guarantee ABI
213       stability if the instance variable layout of a superclass from another
214       parcel changes in a different version.  If you need to access an
215       instance variable from another parcel, add accessor methods.
216
217       A pointer to the ivars struct can be obtained by calling an inline
218       function named "{parcel_nick}_{Class_Name}_IVARS". This function takes
219       the object of the class (typically "self") as argument.
220
221       Example using short names:
222
223           #define C_PFIND_PATH
224           #define PFIND_USE_SHORT_NAMES
225           #include "Pathfinder/Path.h"
226
227           int
228           Path_get_num_nodes(Path *self) {
229               PathIVARS *ivars = Path_IVARS(self);
230               return ivars->num_nodes;
231           }
232
233   Functions
234           function-declaration = function-exposure-specifier?
235                                  function-modifier*
236                                  return-type function-name
237                                  "(" param-list? ")" ";"
238           function-exposure-specifier = "public"
239           function-modifier = "inert" | "inline" | "abstract" | "final"
240           return-type = return-type-qualifier* type
241           return-type-qualifier = "incremented" | "nullable"
242           function-name = identifier
243           param-list = param | param "," param-list
244           param = param-qualifier* type param-name ("=" scalar-constant)?
245           param-name = identifier
246           param-qualifier = "decremented"
247
248       Function exposure
249
250       API documentation will only be generated for functions with "public"
251       exposure.
252
253       Inert functions
254
255       Inert functions are dispatched statically. They are declared in the
256       generated C header with the name
257       "{parcel_nick}_{Class_Nick}_{Function_Name}" and must be defined in a C
258       source file. They must be neither abstract nor final.
259
260       Example:
261
262           public class Pathfinder::Graph::VisibilityGraph nickname VisGraph
263               extends Clownfish::Obj {
264
265               public inert incremented VisibilityGraph*
266               new(int node_capacity);
267           }
268
269       This will generate:
270
271           pfind_VisibilityGraph*
272           pfind_VisGraph_new(int node_capacity);
273
274       The C source file implementing the inert function will typically use
275       short names. So the implementation will look like:
276
277           #define PFIND_USE_SHORT_NAMES
278           #include "Pathfinder/Graph/VisibilityGraph.h"
279
280           VisibilityGraph*
281           VisGraph_new(int node_capacity) {
282               /* Implementation */
283           }
284
285       Inline functions
286
287       Inert functions can be inline. They should be defined as static inline
288       functions in a C block in the Clownfish header file. The macro
289       "CFISH_INLINE" expands to the C compilerXs inline keyword and should be
290       used for portability.
291
292       Methods
293
294       Non-inert functions are dynamically dispatched methods. Their name must
295       start with an uppercase letter and every underscore must be followed by
296       an uppercase letter. Methods must not be declared inline.
297
298       The first parameter of a method must be a pointer to an object of the
299       methodXs class which receives the object on which the method was
300       invoked. By convention, this parameter is named "self".
301
302       For every method, an inline wrapper for dynamic dispatch is defined in
303       the generated C header with the name
304       "{PARCEL_NICK}_{Class_Nick}_{Method_Name}". Additionally, an
305       implementing function is declared with the name
306       "{PARCEL_NICK}_{Class_Nick}_{Method_Name}_IMP". The Clownfish compiler
307       also generates a typedef for the methodXs function pointer type named
308       "{PARCEL_NICK}_{Class_Nick}_{Method_Name}_t". Wrappers and typedefs are
309       created for all subclasses whether they override a method or not.
310
311       Example:
312
313           public class Pathfinder::Graph::VisibilityGraph nickname VisGraph
314               extends Clownfish::Obj {
315
316               public void
317               Add_Node(VisibilityGraph *self, decremented Node *node);
318           }
319
320       This will generate:
321
322           /* Wrapper for dynamic dispatch */
323           static inline void
324           PFIND_VisGraph_Add_Node(pfind_VisibilityGraph *self, pfind_Node *node) {
325               /* Inline code for wrapper */
326           }
327
328           /* Declaration of implementing function */
329           void
330           PFIND_VisGraph_Add_Node_IMP(pfind_VisibilityGraph *self,
331                                       pfind_Node *node);
332
333           /* Declaration of function pointer type */
334           typedef void
335           (*PFIND_VisGraph_Add_Node_t)(pfind_VisibilityGraph *self,
336                                        pfind_Node *node);
337
338       The implementing function of non-abstract methods must be defined in a
339       C source file. This file will typically define the short names macro.
340       So the implementation will look like:
341
342           #define PFIND_USE_SHORT_NAMES
343           #include "Pathfinder/Graph/VisibilityGraph.h"
344
345           void
346           VisGraph_Add_Node_IMP(VisibilityGraph *self, Node *node) {
347               /* Implementation */
348           }
349
350       Looking up methods
351
352       Clownfish defines a macro named "CFISH_METHOD_PTR" that looks up the
353       pointer to the implementing function of a method. The first parameter
354       of the macro is a pointer to the Clownfish::Class object of the
355       methodXs class, the second is the unshortened name of the method
356       wrapper. If short names for the Clownfish parcel are used, the macro is
357       also available under the name "METHOD_PTR".
358
359       To lookup methods from a superclass, thereXs a macro
360       "CFISH_SUPER_METHOD_PTR" with the same parameters.
361
362       Example using short names:
363
364           // Note that the name of the method wrapper must not be shortened.
365           VisGraph_Add_Node_t add_node
366               = METHOD_PTR(VISIBILITYGRAPH, Pfind_VisGraph_Add_Node);
367
368           VisGraph_Add_Node_t super_add_node
369               = SUPER_METHOD_PTR(VISIBILITYGRAPH, Pfind_VisGraph_Add_Node);
370
371       Abstract methods
372
373       For abstract methods, the Clownfish compiler generates an implementing
374       function which throws an error. They should be overridden in a
375       subclass.
376
377       Final methods
378
379       Final methods must not be overridden. They must not be abstract.
380
381       Nullable return type
382
383       If a function has a nullable return type, it must return a pointer.
384       Non-nullable functions must never return the NULL pointer.
385
386       Incremented return type
387
388       Incremented return types must be pointers to Clownfish objects. The
389       function will either return a new object with an initial reference
390       count of 1 or increment the reference count. The caller must decrement
391       the reference count of the returned object when itXs no longer used.
392
393       For returned objects with non-incremented return type, usually no
394       additional handling of reference counts is required. Only if an object
395       is returned from an accessor or a container object and the caller wants
396       to use the object longer than the returning object retains a reference,
397       it must increment the reference count itself and decrement when the
398       object is no longer used.
399
400       Decremented parameters
401
402       Decremented parameters must be pointers to Clownfish objects. The
403       function will either decrement the reference count of the passed-in
404       object or retain a reference without incrementing the reference count.
405       If the caller wants to use the passed-in object afterwards, it usually
406       must increment its reference count before the call and decrement it
407       when itXs no longer used. If the caller does not make further use of
408       the passed-in object, it must not decrement its reference count after
409       the call.
410
411       This is typically used in container classes like Vector:
412
413           String *string = String_newf("Hello");
414           Vec_Push(array, (Obj*)string);
415           // No need to DECREF the string.
416
417       Default parameter values
418
419       Default parameter values can be given as integer, float, or string
420       literals.  The values "true", "false", and "NULL" are also supported.
421       The default values are only used by certain host language bindings.
422       TheyXre not supported when calling a function from C.
423
424   C blocks
425       Clownfish headers can contain C blocks which start with a line
426       containing the string "__C__" and end on a line containing the string
427       "__END_C__". The contents of a C block are copied verbatim to the
428       generated C header.
429
430       Example:
431
432           __C__
433
434           struct pfind_AuxiliaryStruct {
435               int a;
436               int b;
437           };
438
439           __END_C__
440
441   Object life cycle
442       Object creation
443
444       Objects are allocated by invoking the "Make_Obj" method on a classXs
445       Clownfish::Class object.
446
447       Any inert function can be used to construct objects from C. But to
448       support inheritance and object creation from the host language,
449       Clownfish classes need a separate function to initialize objects. The
450       initializer must take a pointer to an object as first argument and
451       return a pointer to the same object. If the parent class has an
452       initializer, it should be called first by the subclassXs initializer.
453
454       By convention, the standard constructor is named "new" and the standard
455       initializer "init".
456
457       Example:
458
459           /* Clownfish header */
460
461           class Vehicle {
462               double max_speed;
463
464               inert Vehicle*
465               init(Vehicle *self, double max_speed);
466           }
467
468           class Train inherits Vehicle {
469               double track_gauge;
470
471               inert incremented Train*
472               new(double max_speed, double track_gauge);
473
474               inert Train*
475               init(Train *self, double max_speed, double track_gauge);
476           }
477
478           /* Implementation */
479
480           Train*
481           Train_new(double max_speed, double track_gauge) {
482               Train *self = (Train*)Class_Make_Obj(TRAIN);
483               return Train_init(self, max_speed, track_gauge);
484           }
485
486           Train*
487           Train_init(Train *self, double max_speed, double track_gauge) {
488               Vehicle_init((Vehicle*)self, max_speed);
489               self->track_gauge = track_gauge;
490               return self;
491           }
492
493       Reference counting
494
495       Clownfish uses reference counting for memory management. Objects are
496       created with a reference count of 1. There are two macros
497       "CFISH_INCREF" and "CFISH_DECREF" to increment and decrement reference
498       counts. If short names for the Clownfish parcel are enabled, the macros
499       can be abbreviated to "INCREF" and "DECREF". Both macros take a pointer
500       to an object as argument.  NULL pointers are allowed. "CFISH_INCREF"
501       returns a pointer to the object.  This value might differ from the
502       passed-in pointer in some cases. So if a reference is retained, the
503       pointer returned from "CFISH_INCREF" should be used. "CFISH_DECREF"
504       returns the modified reference count.
505
506       Examples:
507
508           self->value = INCREF(arg);
509
510           DECREF(object);
511
512       Object destruction
513
514       If an objectXs reference count reaches 0, its "Destroy" method is
515       called.  This public method takes no arguments besides "self" and has
516       no return value.  It should release the resources held by the object
517       and finally call the "Destroy" method of the superclass via the
518       "CFISH_SUPER_DESTROY" macro with short name "SUPER_DESTROY". This macro
519       takes the "self" pointer as first argument and a pointer to the
520       objectXs Clownfish::Class as second argument.  The "Destroy" method of
521       the Clownfish::Obj class will eventually free the object struct.
522
523       Example:
524
525           /* Clownfish header */
526
527           class Path {
528               Vector *nodes;
529
530               public void
531               Destroy(Path *self);
532           }
533
534           /* Implementation */
535
536           void
537           Path_Destroy_IMP(Path *self) {
538               DECREF(self->nodes);
539               SUPER_DESTROY(self, PATH);
540           }
541
542   Documentation
543       The Clownfish compiler creates documentation in the host languageXs
544       preferred format from so-called DocuComments found in the ".cfh" files.
545       DocuComments use Markdown (CommonMark <http://commonmark.org/> flavor)
546       for formatting.  DocuComments are multi-line C-style comments that
547       start with "/**". They immediately precede the documented class, inert
548       function, or method.  A left border consisting of whitespace and
549       asterisks is stripped.
550
551       The DocuComment for a class should start with a short description
552       (everything up until the first period ".") which may appear in the name
553       section of a man page, for example.
554
555       DocuComments for functions and methods may end with a series of @param
556       and @return directives which document the parameters and return values.
557
558       Example:
559
560           /** Class describing a train.
561            *
562            * The Train class describes a train. It extends the Vehicle class and
563            * adds some useful properties specific to trains.
564            */
565           public class Train inherits Vehicle {
566               /** Create a new Train object.
567                *
568                * @param max_speed The maximum speed in km/h.
569                * @param track_gauge The track gauge in mm.
570                */
571               public inert incremented Train*
572               new(double max_speed, double track_gauge);
573
574               /** Accessor for maximum speed.
575                *
576                * @return the maximum speed in km/h.
577                */
578               public double
579               Get_Max_Speed(Train *self);
580           }
581
582       The Clownfish compiler also looks for standalone Markdown ".md" files
583       in the source directories which will be included in the documentation.
584
585
586
587perl v5.36.0                      2022-07-22Clownfish::Docs::WritingClasses(3)
Impressum