Work on standalone Clownfish documentation - Convert existing POD to Markdown - Introduction to Clownfish classes - Build instructions for C environments
Project: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/repo Commit: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/commit/1e257940 Tree: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/tree/1e257940 Diff: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/diff/1e257940 Branch: refs/heads/master Commit: 1e2579403d8491a146f3a0f6e73695a520608117 Parents: fbe310d Author: Nick Wellnhofer <wellnho...@aevum.de> Authored: Mon Jul 27 22:06:31 2015 +0200 Committer: Nick Wellnhofer <wellnho...@aevum.de> Committed: Wed Aug 19 15:40:07 2015 +0200 ---------------------------------------------------------------------- runtime/core/Clownfish.md | 60 ++ runtime/core/Clownfish/Docs/BuildingProjects.md | 112 ++++ runtime/core/Clownfish/Docs/ClassIntro.md | 94 +++ runtime/core/Clownfish/Docs/WritingClasses.md | 534 +++++++++++++++ runtime/perl/lib/Clownfish.pod | 648 ------------------- 5 files changed, 800 insertions(+), 648 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/1e257940/runtime/core/Clownfish.md ---------------------------------------------------------------------- diff --git a/runtime/core/Clownfish.md b/runtime/core/Clownfish.md new file mode 100644 index 0000000..058eb12 --- /dev/null +++ b/runtime/core/Clownfish.md @@ -0,0 +1,60 @@ +# Apache Clownfish symbiotic object system + +Apache Clownfish is a "symbiotic" object system for C which is designed to +pair with a "host" dynamic language environment, facilitating the development +of high performance host language extensions. + +## Features + +* Designed to support multiple host languages. Currently, only Perl is + supported. +* Support for stand-alone C libraries and executables. +* Subclassing and method overriding from the host language. +* Support for host language idioms like named parameters or default argument + values. +* Highly performant object system with lazy creation of host language objects. +* Runtime with classes for commonly used data structures like strings, dynamic + arrays and hash tables. +* Guaranteed ABI stability when adding or reordering methods or instance + variables. +* Modularity. +* Introspection. +* Documentation generator. + +## Planned features + +* Support for more host languages. +* Support for interfaces. + +## Overview + +Clownfish consists of two parts, the Clownfish compiler "CFC" and the +Clownfish runtime. CFC is a code generator that creates C header files, host +language bindings, initialization code and documentation from a set of +Clownfish header files. The generated code is compiled with other project +code and linked with the Clownfish runtime. + +Clownfish header files have a `.cfh` extensions and define classes used within +the Clownfish object system. The object system is implemented in C and +supports single inheritance and virtual method dispatch. CFC creates a C +header file from each Clownfish header containing the C interface to Clownfish +objects. Functions and methods of objects are implemented in normal C source +files. Beyond the C level, CFC can generate host language bindings to make +Clownfish objects accessible from other programming languages. The compiler +also creates class documentation in various formats from comments contained in +Clownfish header files and standalone Markdown files. + +The Clownfish runtime provides: + +* The [](cfish.Obj) class which is the root of the class hierarchy. +* Core data types like [strings](cfish.String), + [dynamic arrays](cfish.Vector), and [hashes](cfish.Hash). +* The [](cfish.Class) metaclass. +* Some helper classes. + +## Documentation + +* [Working with Clownfish classes](ClassIntro) +* [Building Clownfish projects in C environments](BuildingProjects) +* [Writing Clownfish classes](WritingClasses) + http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/1e257940/runtime/core/Clownfish/Docs/BuildingProjects.md ---------------------------------------------------------------------- diff --git a/runtime/core/Clownfish/Docs/BuildingProjects.md b/runtime/core/Clownfish/Docs/BuildingProjects.md new file mode 100644 index 0000000..9b9606b --- /dev/null +++ b/runtime/core/Clownfish/Docs/BuildingProjects.md @@ -0,0 +1,112 @@ +# Building Apache Clownfish projects in C environments + +The following steps are required to build a project that uses +Apache Clownfish: + +- Run the `cfc` command-line application (Clownfish compiler) to + generate C headers, C source files, and documentation. +- Include the C headers generated by the Clownfish compiler in your + own code to [work with Clownfish objects](ClassIntro). +- Compile an additional C source file generated by CFC. +- Link your object code, the object code from the generated file, + and the Clownfish runtime library. + +## Running cfc + + cfc [--source=<dir>] [--include=<dir>] [--parcel=<name>] + --dest=<dir> + [--header=<file>] [--footer=<file>] + +### --source + +Every `--source` argument adds a directory to the list of source +directories to search for source parcels. For every source parcel +found, CFC generates C headers, a C source file, and documentation. + +The source directories are scanned for Clownfish parcel definitions +(`.cfp`), Clownfish headers (`.cfh`), and standalone documentation +in Markdown format (`.md`). + +This option may be specified multiple times. + +### --include + +Every `--include` argument adds a directory to the list of include +directories. CFC generates C headers for parcels from an include +directory only if they're required by a source parcel or if they're +specified with the `--parcel` option. Only C headers are generated +for included parcels, no C source code or documentation. + +The include directories are scanned for Clownfish parcel +definitions (`.cfp`) and Clownfish headers (`.cfh`). + +After the directories specified on the command-line, the following +directories are processed: + +- Directories from the environment variable `CLOWNFISH_INCLUDE`. + This variable contains a colon-separated list of directories. +- On UNIX-like systems `/usr/local/share/clownfish/include` and + `/usr/share/clownfish/include`. + +This option may be specified multiple times. + +### --parcel + +Adds a parcel to the list of prerequisite parcels to make sure that +its C headers are generated. This is useful when running without the +`--source` option. For example, a project that doesn't define its +own Clownfish classes can generate the C headers for the Clownfish +runtime with: + + cfc --parcel=Clownfish --dest=autogen + +This option may be specified multiple times. + +### --dest + +The destination directory for generated files. By convention, +the name `autogen` is used. + +CFC creates the following subdirectories in the destination +directory: + +- `include` contains generated C headers. +- `sources` contains generated C source files. +- `man` contains generated man pages. +- `share/doc/clownfish` contains generated HTML documentation. + +This option is required. + +### --header + +Specifies a file whose contents are added as a comment on top of +each generated file. + +### --footer + +Specifies a file whose contents are added as a comment on the +bottom of each generated file. + +## Including the generated C headers + +The C header files generated with `cfc` can be found in +`autogen/include`. You should add this directory to your compiler's +search path, for example using `-Iautogen/include` under GCC. + +One C header file is generated for every Clownfish header (.cfh) file. +C code that makes use of a class defined in the .cfh file must include +the respective C header. The Clownfish compiler also creates a few +other internal C header files. + +## Compiling the generated source files + +`cfc` creates one source file for every parcel in +`autogen/sources/{parcel_nick}_parcel.c`. These files must be +compiled with `autogen/include` added to the header search path. + +## Linking + +When linking, add the object files of the CFC-generated code created +in the previous step. You must also link the shared library of the +Clownfish runtime (`-lcfish` under GCC). + http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/1e257940/runtime/core/Clownfish/Docs/ClassIntro.md ---------------------------------------------------------------------- diff --git a/runtime/core/Clownfish/Docs/ClassIntro.md b/runtime/core/Clownfish/Docs/ClassIntro.md new file mode 100644 index 0000000..e23fdba --- /dev/null +++ b/runtime/core/Clownfish/Docs/ClassIntro.md @@ -0,0 +1,94 @@ +# Working with Apache Clownfish classes in C + +## Inititalizing Clownfish parcels + +Every Clownfish parcel must be initialized before it is used. The +initialization function is named `{parcel_nick}_bootstrap_parcel` and +takes no arguments. + +Example: + + cfish_bootstrap_parcel(); + +## Including the generated header file + +To use Clownfish classes from C code, the header file generated by the +Clownfish compiler must be included. The name of the C header is +derived from the name of the Clownfish `.cfh` header. It can also be +found in the class documentation. + +Typically, the "short name macro" should be defined before including a +Clownfish header. Its name is derived from the parcel nickname and has +the form `{PARCEL_NICK}_USE_SHORT_NAMES`. If the short name macro is in +effect, you don't have to worry about parcel prefixes. + +Example: + + #define CFISH_USE_SHORT_NAMES + + #include <Clownfish/String.h> + #include <Clownfish/Vector.h> + +## Function and method prefixes + +Clownfish classes can have a "nickname" -- a shorter version of the +class name that is used for function and method prefixes. The nickname +can be found in the class documentation. + +For example the String class has the nickname `Str`. + +## Creating objects + +A Clownfish object is a pointer to an opaque struct. + +Most classes come with one or more constructors. On the C level, a +constructor is simply an "inert" function of a class that returns a +new object. In Clownfish parlance, an inert function is any function +in a class that isn't a method, similar to static methods in Java or +static member functions in C++. + +Example: + + // Notice the use of nickname "Str" in the constructor prefix. + String *name = Str_newf("%s %s", first, last); + +## Calling methods + +Calling methods is straight-forward. The invocant is always passed as +first argument. + + // Notice the use of nickname "Str" in the method prefix. + size_t len = Str_Length(name); + +Method names always start with an uppercase letter. + +## Memory management + +Clownfish uses reference counting to manage memory. Constructors, but +also some methods, return an "incremented" object. If you're done with +an incremented object, you must decrease its reference count to avoid +leaking memory. Use the `DECREF` macro to release an object: + + DECREF(name); + +Some other methods return non-incremented objects. If you want to retain +a reference to such an object, you must increase its reference count +using the `INCREF` macro to make sure it won't be destroyed too early: + + obj = INCREF(obj); + +This invocation of INCREF must be matched by a DECREF when you're done +with the object. + +Some methods, for example in container classes, take "decremented" +objects as arguments. From the caller's perspective, passing a +decremented argument is equivalent to passing a non-decremented argument +and calling DECREF afterwards. Typically, this avoids a call to DECREF +in the calling code. But sometimes, it must be compensated with an +INCREF. + +## Further reading + +* [Building Clownfish projects in C environments](BuildingProjects) +* [Writing Clownfish classes](WritingClasses) + http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/1e257940/runtime/core/Clownfish/Docs/WritingClasses.md ---------------------------------------------------------------------- diff --git a/runtime/core/Clownfish/Docs/WritingClasses.md b/runtime/core/Clownfish/Docs/WritingClasses.md new file mode 100644 index 0000000..c7f5a49 --- /dev/null +++ b/runtime/core/Clownfish/Docs/WritingClasses.md @@ -0,0 +1,534 @@ +# Writing Apache Clownfish classes + +## Parcels + +Every Clownfish class belongs to a Clownfish parcel. Parcels are used for +namespacing and versioning. Information about parcels is stored in `.cfp` +files which contain a JSON hash with the following keys: + +* __name:__ The parcel's name. It must contain only letters. + +* __nickname:__ A short nickname. It must contain only letters. This nickname, + followed by an underscore, is used to prefix generated C symbols and + macros. Depending on the kind of symbol, a lowercase, mixed case, or + uppercase prefix will be used. + +* __version:__ A version specifier of the following form (without whitespace): + + version-specifier = "v" version-number + version-number = digit | digit "." version-number + +* __prerequisites:__ A hash containing the prerequisite parcels. The hash keys + are the parcel names. The values contain the minimum required version. + +An example `.cfp` file might look like: + + { + "name": "Pathfinder", + "nickname": "Pfind", + "version": "v2.3.8", + "prerequisites": { + "Clownfish": "v0.4.0" + } + } + +A parcel specifier of the following form is used in Clownfish header files: + + parcel-specifier = "parcel" parcel-name ";" + parcel-name = identifier + +For example: + + parcel Pathfinder; + +Every `.cfh` file starts with a parcel specifier containing the name of +the parcel for all classes in the header file. + +### Initialization + +Every Clownfish parcel must be initialized before it is used. The +initialization function is named `{parcel_nick}_bootstrap_parcel` and takes +no arguments. + +Example call: + + pfind_bootstrap_parcel(); + +The generated host language bindings call the bootstrap function +automatically. C projects must call the function manually. + +### Short names + +If a macro with the uppercase name `{PARCEL_NICK}_USE_SHORT_NAMES` is +defined before including a generated C header, additional macros without the +parcel prefix will be defined for most symbols. + +Example: + + #define PFIND_USE_SHORT_NAMES + #include <Pathfinder/Graph.h> + #include <Pathfinder/Path.h> + + /* Prefixes can be omitted. */ + Path *path = Graph_Find_Shortest_Path(graph); + + /* Without PFIND_USE_SHORT_NAMES, one would have to write: */ + pfind_Path *path = PFIND_Graph_Find_Shortest_Path(graph); + +For object types in Clownfish header files, prefixes of class structs can +also be omitted unless multiple parcels declare classes with the same last +component of the class name. + +### The "Clownfish" parcel + +The Clownfish runtime classes live in a parcel named `Clownfish` with +nickname `Cfish`. Consequently, the short name macro is named +`CFISH_USE_SHORT_NAMES`. + +## Declaring classes + +Classes are declared in Clownfish header files using a declaration of the +following form: + + class-declaration = class-exposure-specifier? + class-modifier* + "class" class-name + ("nickname" class-nickname)? + ("inherits" class-name)? + "{" class-contents "}" + class-exposure-specifier = "public" + class-modifier = "inert" | "final" + class-name = identifier | identifier "::" class-name + class-nickname = identifier + class-contents = (variable-declaration | function-declaration)* + +Class name components must start with an uppercase letter and must not contain +underscores. The last component must contain at least one lowercase letter and +must be unique for every class in a parcel. + +For every class, a type with the name `{parcel_nick}_{Class_Last_Comp}` +is defined in the generated C header. This is an opaque typedef used to +ensure type safety. + +For every class, a global variable with the uppercase name +`{PARCEL_NICK}_{CLASS_LAST_COMP}` is defined. This variable is a pointer to +a Clownfish::Class object which is initialized when bootstrapping the parcel. + +Non-inert classes inherit from Clownfish::Obj by default. + +Example of a class declaration: + + parcel Pathfinder; + + public class Pathfinder::Graph::VisibilityGraph nickname VisGraph + extends Clownfish::Obj { + /* Variables and functions */ + } + +This will generate: + + typedef struct pfind_VisibilityGraph pfind_VisibilityGraph; + extern cfish_Class *PFIND_VISIBILITYGRAPH; + +### Class exposure + +TODO + +### Inert classes + +Inert classes must contain only inert variables or inert functions, that is, +neither instance variables nor methods. They must not inherit from another +class or be inherited from. They're essentially nothing more than a +namespace for functions and global variables. + +### Final classes + +For final classes, every method is made final, regardless of the method +modifier. Final classes must not be inherited from. + +## Variables + +Variables are declared with a declaration of the following form: + + variable-declaration = variable-exposure-specifier? + variable-modifier* + type variable-name ";" + variable-exposure-specifier = "public" + variable-modifier = "inert" + variable-name = identifier + +### Inert variables + +Inert variables are global class variables of which only a single copy +exists. They are declared in the generated C header with the name +`{parcel_nick}_{Class_Nick}_{Variable_Name}` and must be defined in a C +source file. + +Example: + + public class Pathfinder::Path { + public inert int max_path_length; + } + +This will generate: + + extern int pfind_Path_max_path_length; + +The C source file defining the variable will typically use short names. So the +definition will look like: + + int Path_max_path_length = 5000; + +### Inert variable exposure + +TODO + +### Instance variables + +Non-inert variables are instance variables and added to the class's ivars +struct. They must not have an exposure specifier. + +Example: + + public class Pathfinder::Path { + int num_nodes; + + public int + Get_Num_Nodes(Path *self); + } + +This will add a `num_nodes` member to the ivars struct of `Path`. + +### The ivars struct + +To access instance variables, the macro `C_{PARCEL_NICK}_{CLASS_LAST_COMP}` +must be defined before including the generated header file. This will make +a struct named `{parcel_nick}_{Class_Name}IVARS` with a corresponding +typedef and short name available that contains all instance variables +of the class and all superclasses from the same parcel. Instance +variables defined in other parcels are not accessible. This is by +design to guarantee ABI stability if the instance variable layout +of a superclass from another parcel changes in a different version. +If you need to access an instance variable from another parcel, +add accessor methods. + +A pointer to the ivars struct can be obtained by calling an inline +function named `{parcel_nick}_{Class_Name}_IVARS`. This function +takes the object of the class (typically `self`) as argument. + +Example using short names: + + #define C_PFIND_PATH + #define PFIND_USE_SHORT_NAMES + #include "Pathfinder/Path.h" + + int + Path_get_num_nodes(Path *self) { + PathIVARS *ivars = Path_IVARS(self); + return ivars->num_nodes; + } + +## Functions + + function-declaration = function-exposure-specifier? + function-modifier* + return-type function-name + "(" param-list? ")" ";" + function-exposure-specifier = "public" + function-modifier = "inert" | "inline" | "abstract" | "final" + return-type = return-type-qualifier* type + return-type-qualifier = "incremented" | "nullable" + function-name = identifier + param-list = param | param "," param-list + param = param-qualifier* type param-name ("=" scalar-constant)? + param-name = identifier + param-qualifier = "decremented" + +### Function exposure + +TODO + +### Inert functions + +Inert functions are dispatched statically. They are declared in the generated +C header with the name `{parcel_nick}_{Class_Nick}_{Function_Name}` +and must be defined in a C source file. They must be neither abstract nor +final. + +Example: + + public class Pathfinder::Graph::VisibilityGraph nickname VisGraph + extends Clownfish::Obj { + + public inert incremented VisibilityGraph* + new(int node_capacity); + } + +This will generate: + + pfind_VisibilityGraph* + pfind_VisGraph_new(int node_capacity); + +The C source file implementing the inert function will typically use short +names. So the implementation will look like: + + #define PFIND_USE_SHORT_NAMES + #include "Pathfinder/Graph/VisibilityGraph.h" + + VisibilityGraph* + VisGraph_new(int node_capacity) { + /* Implementation */ + } + +### Inline functions + +Inert functions can be inline. They should be defined as static inline +functions in a C block in the Clownfish header file. The macro `CFISH_INLINE` +expands to the C compiler's inline keyword and should be used for portability. + +### Methods + +Non-inert functions are dynamically dispatched methods. Their name must start +with an uppercase letter and every underscore must be followed by an uppercase +letter. Methods must not be declared inline. + +The first parameter of a method must be a pointer to an object of the method's +class which receives the object on which the method was invoked. By convention, +this parameter is named `self`. + +For every method, an inline wrapper for dynamic dispatch is defined in +the generated C header with the name +`{PARCEL_NICK}_{Class_Nick}_{Method_Name}`. Additionally, an +implementing function is declared with the name +`{PARCEL_NICK}_{Class_Nick}_{Method_Name}_IMP`. The Clownfish compiler also +generates a typedef for the method's function pointer type named +`{PARCEL_NICK}_{Class_Nick}_{Method_Name}_t`. Wrappers and typedefs are +created for all subclasses whether they override a method or not. + +Example: + + public class Pathfinder::Graph::VisibilityGraph nickname VisGraph + extends Clownfish::Obj { + + public void + Add_Node(VisibilityGraph *self, decremented Node *node); + } + +This will generate: + + /* Wrapper for dynamic dispatch */ + static inline void + PFIND_VisGraph_Add_Node(pfind_VisibilityGraph *self, pfind_Node *node) { + /* Inline code for wrapper */ + } + + /* Declaration of implementing function */ + void + PFIND_VisGraph_Add_Node_IMP(pfind_VisibilityGraph *self, + pfind_Node *node); + + /* Declaration of function pointer type */ + typedef void + (*PFIND_VisGraph_Add_Node_t)(pfind_VisibilityGraph *self, + pfind_Node *node); + +The implementing function of non-abstract methods must be defined in a C source +file. This file will typically define the short names macro. So the +implementation will look like: + + #define PFIND_USE_SHORT_NAMES + #include "Pathfinder/Graph/VisibilityGraph.h" + + void + VisGraph_Add_Node_IMP(VisibilityGraph *self, Node *node) { + /* Implementation */ + } + +### Looking up function pointers + +Clownfish defines a macro named `CFISH_METHOD_PTR` that looks up the pointer +to the implementing function of a method. The first parameter of the macro is +a pointer to the Clownfish::Class object of the method's class, the second is +the unshortened name of the method wrapper. If short names for the Clownfish +parcel are used, the macro is also available under the name `METHOD_PTR`. + +To lookup methods from a superclass, there's a macro `CFISH_SUPER_METHOD_PTR` +with the same parameters. + +Example using short names: + + VisGraph_Add_Node_t add_node + = METHOD_PTR(PFIND_VISIBILITYGRAPH, Pfind_VisGraph_Add_Node); + + VisGraph_Add_Node_t super_add_node + = SUPER_METHOD_PTR(PFIND_VISIBILITYGRAPH, Pfind_VisGraph_Add_Node); + +### Abstract methods + +For abstract methods, the Clownfish compiler generates an implementing function +which throws an error. They should be overridden in a subclass. + +### Final methods + +Final methods must not be overridden. They must not be abstract. + +### Nullable return type + +If a function has a nullable return type, it must return a pointer. +Non-nullable functions must never return the NULL pointer. + +### Incremented return type + +Incremented return types must be pointers to Clownfish objects. The function +will either return a new object with an initial reference count of 1 or +increment the reference count. The caller must decrement the reference count of +the returned object when it's no longer used. + +For returned objects with non-incremented return type, usually no additional +handling of reference counts is required. Only if an object is returned from an +accessor or a container object and the caller wants to use the object longer +than the returning object retains a reference, it must increment the reference +count itself and decrement when the object is no longer used. + +### Decremented parameters + +Decremented parameters must be pointers to Clownfish objects. The function +will either decrement the reference count of the passed-in object or retain a +reference without incrementing the reference count. If the caller wants to use +the passed-in object afterwards, it usually must increment its reference count +before the call and decrement it when it's no longer used. If the caller does +not make further use of the passed-in object, it must not decrement its +reference count after the call. + +This is typically used in container classes like Vector: + + String *string = String_newf("Hello"); + Vec_Push(array, (Obj*)string); + // No need to DECREF the string. + +### Default parameter values + +Default parameter values can be given as integer, float, or string literals. +The values `true`, `false`, and `NULL` are also supported. The default +values are only used by the host language bindings. They're not supported +when calling a function from C. + +## C blocks + +Clownfish headers can contain C blocks which start with a line containing the +string `__C__` and end on a line containing the string `__END_C__`. The +contents of a C block are copied verbatim to the generated C header. + +Example: + + __C__ + + struct pfind_AuxiliaryStruct { + int a; + int b; + }; + + __END_C__ + +## Object life cycle + +### Object creation + +Objects are allocated by invoking the `Make_Obj` method on a class's +Clownfish::Class object. + +Any inert function can be used to construct objects from C. But to support +inheritance and object creation from the host language, Clownfish classes +need a separate function to initialize objects. The initializer must take a +pointer to an object as first argument and return a pointer to the same +object. If the parent class has an initializer, it should be called first by +the subclass's initializer. + +By convention, the standard constructor is named `new`. If a class has an +inert function named `init`, it is used as initializer to create a host +language constructor by default. + +Example: + + /* Clownfish header */ + + class Vehicle { + double max_speed; + + inert Vehicle* + init(Vehicle *self, double max_speed); + } + + class Train inherits Vehicle { + double track_gauge; + + inert incremented Train* + new(double max_speed, double track_gauge); + + inert Train* + init(Train *self, double max_speed, double track_gauge); + } + + /* Implementation */ + + Train* + Train_new(double max_speed, double track_gauge) { + Train *self = (Train*)Class_Make_Obj(TRAIN); + return Train_init(self, max_speed, track_gauge); + } + + Train* + Train_init(Train *self, double max_speed, double track_gauge) { + Vehicle_init((Vehicle*)self, max_speed); + self->track_gauge = track_gauge; + return self; + } + +### Reference counting + +Clownfish uses reference counting for memory management. Objects are created +with a reference count of 1. There are two macros `CFISH_INCREF` and +`CFISH_DECREF` to increment and decrement reference counts. If short names +for the Clownfish parcel are enabled, the macros can be abbreviated to +`INCREF` and `DECREF`. Both macros take a pointer to an object as argument. +NULL pointers are allowed. `CFISH_INCREF` returns a pointer to the object. +This value might differ from the passed-in pointer in some cases. So if a +reference is retained, the pointer returned from `CFISH_INCREF` should be +used. `CFISH_DECREF` returns the modified reference count. + +Examples: + + self->value = INCREF(arg); + + DECREF(object); + +### Object destruction + +If an object's reference count reaches 0, its `Destroy` method is called. +This public method takes no arguments besides `self` and has no return value. +It should release the resources held by the object and finally call the +`Destroy` method of the superclass via the `CFISH_SUPER_DESTROY` macro with +short name `SUPER_DESTROY`. This macro takes the `self` pointer as first +argument and a pointer to the object's Clownfish::Class as second argument. +The `Destroy` method of the Clownfish::Obj class will eventually free the +object struct. + +Example: + + /* Clownfish header */ + + class Path { + Vector *nodes; + + public void + Destroy(Path *self); + } + + /* Implementation */ + + void + Path_Destroy_IMP(Path *self) { + DECREF(self->nodes); + SUPER_DESTROY(self, PATH); + } + http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/1e257940/runtime/perl/lib/Clownfish.pod ---------------------------------------------------------------------- diff --git a/runtime/perl/lib/Clownfish.pod b/runtime/perl/lib/Clownfish.pod deleted file mode 100644 index e94e595..0000000 --- a/runtime/perl/lib/Clownfish.pod +++ /dev/null @@ -1,648 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -=head1 NAME - -Clownfish - Apache Clownfish symbiotic object system. - -=head1 VERSION - -0.4.0 - -=head1 DESCRIPTION - -Apache Clownfish is a "symbiotic" object system for C which is designed to -pair with a "host" dynamic language environment, facilitating the development -of high performance host language extensions. Clownfish classes are -declared in header files with a C<.cfh> extension. The Clownfish headers -are used by the Clownfish compiler to generate C header files and host -language bindings. Methods, functions and variables are defined in normal -C source files. - -=head2 Features - -=over - -=item * - -Designed to support multiple host languages. Currently, only Perl is supported. - -=item * - -Support for stand-alone C libraries and executables. - -=item * - -Subclassing and method overriding from the host language. - -=item * - -Support for host language idioms like named parameters or default argument -values. - -=item * - -Highly performant object system with lazy creation of host language objects. - -=item * - -Runtime with classes for commonly used data structures like strings, dynamic -arrays and hash tables. - -=item * - -Guaranteed ABI stability when adding or reordering methods or instance -variables. - -=item * - -Modularity. - -=item * - -Introspection. - -=item * - -Documentation generator. - -=back - -=head2 Planned features - -=over - -=item * - -Support for more host languages. - -=back - -=head1 USING CLOWNFISH CLASSES - -TODO: Simple introduction - -=head1 WRITING CLOWNFISH CLASSES - -=head2 Parcels - -Every Clownfish class belongs to a Clownfish parcel. Parcels are used for -namespacing and versioning. Information about parcels is stored in C<.cfp> -files which contain a JSON hash with the following keys: - -=over - -=item name - -The parcel's name. It must contain only letters. - -=item nickname - -A short nickname. It must contain only letters. This nickname, followed by an -underscore, is used to prefix generated C symbols and macros. Depending on the -kind of symbol, a lowercase, mixed case, or uppercase prefix will be used. - -=item version - -A version specifier of the following form (without whitespace): - - version-specifier = "v" version-number - version-number = digit | digit "." version-number - -=item prerequisites - -A hash containing the prerequisite parcels. The hash keys are the parcel -names. The values contain the minimum required version. - -=back - -An example C<.cfp> file might look like: - - { - "name": "Pathfinder", - "nickname": "Pfind", - "version": "v2.3.8", - "prerequisites": { - "Clownfish": "v0.4.0" - } - } - -A parcel specifier of the following form is used in Clownfish header files: - - parcel-specifier = "parcel" parcel-name ";" - parcel-name = identifier - -For example: - - parcel Pathfinder; - -Every C<.cfh> file starts with a parcel specifier containing the name of -the parcel for all classes in the header file. - -=head3 Initialization - -Every Clownfish parcel must be initialized before it is used. The -initialization function is named C<{parcel_nick}_bootstrap_parcel> and takes -no arguments. - -Example call: - - pfind_bootstrap_parcel(); - -The generated host language bindings call the bootstrap function -automatically. C projects must call the function manually. - -=head3 Short names - -If a macro with the uppercase name C<{PARCEL_NICK}_USE_SHORT_NAMES> is -defined before including a generated C header, additional macros without the -parcel prefix will be defined for most symbols. - -Example: - - #define PFIND_USE_SHORT_NAMES - #include <Pathfinder/Graph.h> - #include <Pathfinder/Path.h> - - /* Prefixes can be omitted. */ - Path *path = Graph_Find_Shortest_Path(graph); - - /* Without PFIND_USE_SHORT_NAMES, one would have to write: */ - pfind_Path *path = PFIND_Graph_Find_Shortest_Path(graph); - -For object types in Clownfish header files, prefixes of class structs can -also be omitted unless multiple parcels declare classes with the same last -component of the class name. - -=head3 The "Clownfish" parcel - -The Clownfish runtime classes live in a parcel named C<Clownfish> with -nickname C<Cfish>. Consequently, the short name macro is named -C<CFISH_USE_SHORT_NAMES>. - -=head2 Declaring classes - -Classes are declared in Clownfish header files using a declaration of the -following form: - - class-declaration = class-exposure-specifier? - class-modifier* - "class" class-name - ("nickname" class-nickname)? - ("inherits" class-name)? - "{" class-contents "}" - class-exposure-specifier = "public" - class-modifier = "inert" | "final" - class-name = identifier | identifier "::" class-name - class-nickname = identifier - class-contents = (variable-declaration | function-declaration)* - -Class name components must start with an uppercase letter and must not contain -underscores. The last component must contain at least one lowercase letter and -must be unique for every class in a parcel. - -For every class, a type with the name C<{parcel_nick}_{Class_Last_Comp}> -is defined in the generated C header. This is an opaque typedef used to -ensure type safety. - -For every class, a global variable with the uppercase name -C<{PARCEL_NICK}_{CLASS_LAST_COMP}> is defined. This variable is a pointer to -a Clownfish::Class object which is initialized when bootstrapping the parcel. - -Non-inert classes inherit from Clownfish::Obj by default. - -Example of a class declaration: - - parcel Pathfinder; - - public class Pathfinder::Graph::VisibilityGraph nickname VisGraph - extends Clownfish::Obj { - /* Variables and functions */ - } - -This will generate: - - typedef struct pfind_VisibilityGraph pfind_VisibilityGraph; - extern cfish_Class *PFIND_VISIBILITYGRAPH; - -=head3 Class exposure - -TODO - -=head3 Inert classes - -Inert classes must contain only inert variables or inert functions, that is, -neither instance variables nor methods. They must not inherit from another -class or be inherited from. They're essentially nothing more than a -namespace for functions and global variables. - -=head3 Final classes - -For final classes, every method is made final, regardless of the method -modifier. Final classes must not be inherited from. - -=head2 Variables - -Variables are declared with a declaration of the following form: - - variable-declaration = variable-exposure-specifier? - variable-modifier* - type variable-name ";" - variable-exposure-specifier = "public" - variable-modifier = "inert" - variable-name = identifier - -=head3 Inert variables - -Inert variables are global class variables of which only a single copy -exists. They are declared in the generated C header with the name -C<{parcel_nick}_{Class_Nick}_{Variable_Name}> and must be defined in a C -source file. - -Example: - - public class Pathfinder::Path { - public inert int max_path_length; - } - -This will generate: - - extern int pfind_Path_max_path_length; - -The C source file defining the variable will typically use short names. So the -definition will look like: - - int Path_max_path_length = 5000; - -=head3 Inert variable exposure - -TODO - -=head3 Instance variables - -Non-inert variables are instance variables and added to the class's ivars -struct. They must not have an exposure specifier. - -Example: - - public class Pathfinder::Path { - int num_nodes; - - public int - Get_Num_Nodes(Path *self); - } - -This will add a C<num_nodes> member to the ivars struct of C<Path>. - -=head3 The ivars struct - -To access instance variables, the macro C<C_{PARCEL_NICK}_{CLASS_LAST_COMP}> -must be defined before including the generated header file. This will make -a struct named C<{parcel_nick}_{Class_Name}IVARS> with a corresponding -typedef and short name available that contains all instance variables -of the class and all superclasses from the same parcel. Instance -variables defined in other parcels are not accessible. This is by -design to guarantee ABI stability if the instance variable layout -of a superclass from another parcel changes in a different version. -If you need to access an instance variable from another parcel, -add accessor methods. - -A pointer to the ivars struct can be obtained by calling an inline -function named C<{parcel_nick}_{Class_Name}_IVARS>. This function -takes the object of the class (typically C<self>) as argument. - -Example using short names: - - #define C_PFIND_PATH - #define PFIND_USE_SHORT_NAMES - #include "Pathfinder/Path.h" - - int - Path_get_num_nodes(Path *self) { - PathIVARS *ivars = Path_IVARS(self); - return ivars->num_nodes; - } - -=head2 Functions - - function-declaration = function-exposure-specifier? - function-modifier* - return-type function-name - "(" param-list? ")" ";" - function-exposure-specifier = "public" - function-modifier = "inert" | "inline" | "abstract" | "final" - return-type = return-type-qualifier* type - return-type-qualifier = "incremented" | "nullable" - function-name = identifier - param-list = param | param "," param-list - param = param-qualifier* type param-name ("=" scalar-constant)? - param-name = identifier - param-qualifier = "decremented" - -=head3 Function exposure - -TODO - -=head3 Inert functions - -Inert functions are dispatched statically. They are declared in the generated -C header with the name C<{parcel_nick}_{Class_Nick}_{Function_Name}> -and must be defined in a C source file. They must be neither abstract nor -final. - -Example: - - public class Pathfinder::Graph::VisibilityGraph nickname VisGraph - extends Clownfish::Obj { - - public inert incremented VisibilityGraph* - new(int node_capacity); - } - -This will generate: - - pfind_VisibilityGraph* - pfind_VisGraph_new(int node_capacity); - -The C source file implementing the inert function will typically use short -names. So the implementation will look like: - - #define PFIND_USE_SHORT_NAMES - #include "Pathfinder/Graph/VisibilityGraph.h" - - VisibilityGraph* - VisGraph_new(int node_capacity) { - /* Implementation */ - } - -=head3 Inline functions - -Inert functions can be inline. They should be defined as static inline -functions in a C block in the Clownfish header file. The macro C<CFISH_INLINE> -expands to the C compiler's inline keyword and should be used for portability. - -=head3 Methods - -Non-inert functions are dynamically dispatched methods. Their name must start -with an uppercase letter and every underscore must be followed by an uppercase -letter. Methods must not be declared inline. - -The first parameter of a method must be a pointer to an object of the method's -class which receives the object on which the method was invoked. By convention, -this parameter is named C<self>. - -For every method, an inline wrapper for dynamic dispatch is defined in -the generated C header with the name -C<{PARCEL_NICK}_{Class_Nick}_{Method_Name}>. Additionally, an -implementing function is declared with the name -C<{PARCEL_NICK}_{Class_Nick}_{Method_Name}_IMP>. The Clownfish compiler also -generates a typedef for the method's function pointer type named -C<{PARCEL_NICK}_{Class_Nick}_{Method_Name}_t>. Wrappers and typedefs are -created for all subclasses whether they override a method or not. - -Example: - - public class Pathfinder::Graph::VisibilityGraph nickname VisGraph - extends Clownfish::Obj { - - public void - Add_Node(VisibilityGraph *self, decremented Node *node); - } - -This will generate: - - /* Wrapper for dynamic dispatch */ - static inline void - PFIND_VisGraph_Add_Node(pfind_VisibilityGraph *self, pfind_Node *node) { - /* Inline code for wrapper */ - } - - /* Declaration of implementing function */ - void - PFIND_VisGraph_Add_Node_IMP(pfind_VisibilityGraph *self, - pfind_Node *node); - - /* Declaration of function pointer type */ - typedef void - (*PFIND_VisGraph_Add_Node_t)(pfind_VisibilityGraph *self, - pfind_Node *node); - -The implementing function of non-abstract methods must be defined in a C source -file. This file will typically define the short names macro. So the -implementation will look like: - - #define PFIND_USE_SHORT_NAMES - #include "Pathfinder/Graph/VisibilityGraph.h" - - void - VisGraph_Add_Node_IMP(VisibilityGraph *self, Node *node) { - /* Implementation */ - } - -=head3 Looking up function pointers - -Clownfish defines a macro named C<CFISH_METHOD_PTR> that looks up the pointer -to the implementing function of a method. The first parameter of the macro is -a pointer to the Clownfish::Class object of the method's class, the second is -the unshortened name of the method wrapper. If short names for the Clownfish -parcel are used, the macro is also available under the name C<METHOD_PTR>. - -To lookup methods from a superclass, there's a macro C<CFISH_SUPER_METHOD_PTR> -with the same parameters. - -Example using short names: - - VisGraph_Add_Node_t add_node - = METHOD_PTR(PFIND_VISIBILITYGRAPH, Pfind_VisGraph_Add_Node); - - VisGraph_Add_Node_t super_add_node - = SUPER_METHOD_PTR(PFIND_VISIBILITYGRAPH, Pfind_VisGraph_Add_Node); - -=head3 Abstract methods - -For abstract methods, the Clownfish compiler generates an implementing function -which throws an error. They should be overridden in a subclass. - -=head3 Final methods - -Final methods must not be overridden. They must not be abstract. - -=head3 Nullable return type - -If a function has a nullable return type, it must return a pointer. -Non-nullable functions must never return the NULL pointer. - -=head3 Incremented return type - -Incremented return types must be pointers to Clownfish objects. The function -will either return a new object with an initial reference count of 1 or -increment the reference count. The caller must decrement the reference count of -the returned object when it's no longer used. - -For returned objects with non-incremented return type, usually no additional -handling of reference counts is required. Only if an object is returned from an -accessor or a collection object and the caller wants to use the object longer -than the returning object retains a reference, it must increment the reference -count itself and decrement when the object is no longer used. - -=head3 Decremented parameters - -Decremented parameters must be pointers to Clownfish objects. The function -will either decrement the reference count of the passed-in object or retain a -reference without incrementing the reference count. If the caller wants to use -the passed-in object afterwards, it usually must increment its reference count -before the call and decrement it when it's no longer used. If the caller does -not make further use of the passed-in object, it must not decrement its -reference count after the call. - -This is typically used in container classes like Vector: - - String *string = String_newf("Hello"); - Vec_Push(array, (Obj*)string); - // No need to DECREF the string. - -=head3 Default parameter values - -Default parameter values can be given as integer, float, or string literals. -The values C<true>, C<false>, and C<NULL> are also supported. The default -values are only used by the host language bindings. They're not supported -when calling a function from C. - -=head2 C blocks - -Clownfish headers can contain C blocks which start with a line containing the -string C<__C__> and end on a line containing the string C<__END_C__>. The -contents of a C block are copied verbatim to the generated C header. - -Example: - - __C__ - - struct pfind_AuxiliaryStruct { - int a; - int b; - }; - - __END_C__ - -=head2 Object life cycle - -=head3 Object creation - -Objects are allocated by invoking the C<Make_Obj> method on a class's -Clownfish::Class object. - -Any inert function can be used to construct objects from C. But to support -inheritance and object creation from the host language, Clownfish classes -need a separate function to initialize objects. The initializer must take a -pointer to an object as first argument and return a pointer to the same -object. If the parent class has an initializer, it should be called first by -the subclass's initializer. - -By convention, the standard constructor is named C<new>. If a class has an -inert function named C<init>, it is used as initializer to create a host -language constructor by default. - -Example: - - /* Clownfish header */ - - class Vehicle { - double max_speed; - - inert Vehicle* - init(Vehicle *self, double max_speed); - } - - class Train inherits Vehicle { - double track_gauge; - - inert incremented Train* - new(double max_speed, double track_gauge); - - inert Train* - init(Train *self, double max_speed, double track_gauge); - } - - /* Implementation */ - - Train* - Train_new(double max_speed, double track_gauge) { - Train *self = (Train*)Class_Make_Obj(TRAIN); - return Train_init(self, max_speed, track_gauge); - } - - Train* - Train_init(Train *self, double max_speed, double track_gauge) { - Vehicle_init((Vehicle*)self, max_speed); - self->track_gauge = track_gauge; - return self; - } - -=head3 Reference counting - -Clownfish uses reference counting for memory management. Objects are created -with a reference count of 1. There are two macros C<CFISH_INCREF> and -C<CFISH_DECREF> to increment and decrement reference counts. If short names -for the Clownfish parcel are enabled, the macros can be abbreviated to -C<INCREF> and C<DECREF>. Both macros take a pointer to an object as argument. -NULL pointers are allowed. C<CFISH_INCREF> returns a pointer to the object. -This value might differ from the passed-in pointer in some cases. So if a -reference is retained, the pointer returned from C<CFISH_INCREF> should be -used. C<CFISH_DECREF> returns the modified reference count. - -Examples: - - self->value = INCREF(arg); - - DECREF(object); - -=head3 Object destruction - -If an object's reference count reaches 0, its C<Destroy> method is called. -This public method takes no arguments besides C<self> and has no return value. -It should release the resources held by the object and finally call the -C<Destroy> method of the superclass via the C<CFISH_SUPER_DESTROY> macro with -short name C<SUPER_DESTROY>. This macro takes the C<self> pointer as first -argument and a pointer to the object's Clownfish::Class as second argument. -The C<Destroy> method of the Clownfish::Obj class will eventually free the -object struct. - -Example: - - /* Clownfish header */ - - class Path { - Vector *nodes; - - public void - Destroy(Path *self); - } - - /* Implementation */ - - void - Path_Destroy_IMP(Path *self) { - DECREF(self->nodes); - SUPER_DESTROY(self, PATH); - } - -=head1 COPYRIGHT - -Clownfish is distributed under the Apache License, Version 2.0, as described -in the file C<LICENSE> included with the distribution. - -=cut -