From 2484929a7ddcd673b03c8e9395c5c1722a012943 Mon Sep 17 00:00:00 2001 From: heck Date: Mon, 5 Jun 2023 13:16:49 +0200 Subject: [PATCH] Create dir for lm-c99 and separate its spec and project README.md --- README.md | 235 +++------------------------------------------ lm-c99/lms-c99.md | 237 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 249 insertions(+), 223 deletions(-) create mode 100644 lm-c99/lms-c99.md diff --git a/README.md b/README.md index 145ae52..f74208e 100644 --- a/README.md +++ b/README.md @@ -1,236 +1,25 @@ - -* [pEpACIDLang - Language Mapping Specification LMS-C99](#pepacidlang---language-mapping-specification-lms-c99) - * [About This Document](#about-this-document) - * [IDL-Types](#idl-types) - * [Type Classes](#type-classes) - * [IDL-Type Mapping To C](#idl-type-mapping-to-c) - * [Creation and Destruction](#creation-and-destruction) - * [Primitive Types](#primitive-types) - * [Object Types](#object-types) - * [Allocators](#allocators) - * [Destructors](#destructors) - * [Method Parameters](#method-parameters) - * [Rules For Parameter Allocation](#rules-for-parameter-allocation) - * [Parameter Passing Modes](#parameter-passing-modes) - * [Mapping Table for C](#mapping-table-for-c) - * [Rules For Parameters Of Primitive-Type](#rules-for-parameters-of-primitive-type) - * [Rules For Parameters Of Object-Type](#rules-for-parameters-of-object-type) - * [Read](#read) - * [Update](#update) - * [Consume](#consume) - * [Produce](#produce) - * [Rules For Multithreading](#rules-for-multithreading) - - -# pEpACIDLang - Language Mapping Specification LMS-C99 +# pEpACIDLang + +"The current problem at hand is to replace a handwritten C API with a pEpACIDlang generated one." pEpACIDLang stands for "pEp Abstract C Interface Description Language". pEpACIDLang is language to describe a programming interface. 'Abstract', because the interfaces defined in pEpACIDLang are agnostic to the target language. -'C' because the syntax and some concepts are based on the C language. - -A concrete interface and client code using the interface can be generated for any language where there exist both: -* a language mapping specification -* an interface generator - -The interface generator implements parts of the language mapping specification. -The current problem at hand is to replace a handwritten C API with a pEpACIDlang generated one. - -This is the document specifying the language mapping for C99. - -## About This Document - -State: Draft, to be reviewed with fdik and positron. - -**ATTENTION, IMPORTANT** -In this document, all types expressed as T are the IDL-types, not their corresponding c-types. -An example for clarity: -If `T` is the type `string`, the IDL-type `string` is meant, so the c-type of `T*` is `char**`. - -Usually a variable typename is expressed as `T`. But sometimes `T` is being used to refer to an instance of type `T`. -This imprecision is used for brevity, but only where the context does not allow for an ambiguity. - -## IDL-Types - -### Type Classes - -There are only two type-classes. - -* Primitive Types -* Object Types - -### IDL-Type Mapping To C - -| Type-Class | IDL-Type | C-Type | -|------------|-----------|--------------| -| Primitive | int | int | -| Primitive | uint | unsigned int | -| Primitive | size | size_t | -| Primitive | bool | bool | -| Primitive | enum | enum | -| Object | struct | struct* | -| Object | string | char* | -| Object | binary | char* | -| Object | opaque | void* | -| Object | list\ | list_T* | -| Object | pair | pair_F_S* | - -### Creation and Destruction - -#### Primitive Types - -* Primitive types are always statically allocated -* Primitive types are trivially constructable and destroyable -* All storage classes (auto/static/extern/register) are allowed - -#### Object Types - -For any object-type `T`, corresponding `new` and `free` methods are being generated. - -To create an object of type `T` correctly, there are two ways: - -1. Using its allocator-method -2. Using any method that has a parameter of type `T` with mode `Produce` - -To destroy an object of type `T` correctly, the only way is to use its destructor-method. - -##### Allocators - -The allocator-method has the signature: -`IDL_STATUS new_T(T*)` - -* The memory for `T` has to be dynamically allocated -* An empty object is being created. Any object-types reachable through `T` are pointing to `NULL`. - -Result: -STATUS_OK - `T*` is pointing to a valid object -STATUS_ERROR - Dereferencing of `T*` is undefined behaviour - -##### Destructors - -The destructor-method has the signature: -`IDL_STATUS free_T(T*)` - -1. For all object-type members of `T` itself, their respective destructor-methods are being called -2. The memory for `T` is freed compatibly to how it was allocated using its allocator-method -3. `T*` is set to `NULL` - -Result: -STATUS_OK - All memory reachable through `T*` is freed and `T*` is NULL -STATUS_ERROR - FATAL (most implementations of `free()` can guarantee this will never happen) - -## Method Parameters - -The main concerns when sharing memory (e.g. in form of parameters) are: - -* Ownership: defined as who is allowed and responsible to destroy an object. -* Mutability: Who is allowed to change the contents of the memory location that is known to several parties. - -In environments where memory management is explicit, the lifecycle of data in memory is: - -1. Memory being allocated -2. Memory being shared with producers/consumers (e.g. as a parameter Read/Update/Consume) -3. Read/write operations by multiple parties (needs synchronization if multithreaded environment) -3. Make sure this memory will never be accessed again by nobody -4. Memory has to be freed exactly once and compatibly to how it was allocated - -Every such lifecycle must be completed. -All of this must be guaranteed. - -### Rules For Parameter Allocation - -Parameters have to be allocated as follows: - -* Primitive-types: The general rules outlined under [Creation and Destruction](#creation-and-destruction) apply -* Object-types: Using the allocator- and destructor-methods outlined under [Creation and Destruction](#creation-and-destruction) - -These rules apply regardless of the parameter passing mode. - -### Parameter Passing Modes - -The modes are named by describing what the callee does, from the perspective of the callee, using one verb. - -* `Read` - Immutable, ownership remains with caller -* `Update` - Mutable, ownership remains with caller -* `Consume` - Mutable, ownership goes to callee -* `Produce` - Immutable, ownership goes to caller - -#### Mapping Table for C - -Type of `T` as a function of type-class and mode. -Where `T` any of the respective IDL-Types (not their respective c-type, as mentioned in [About This Document](#about-this-document)). - -| Mode/Type-Class | READ | UPDATE | CONSUME | PRODUCE | -|------------------|------|--------|---------|---------| -| Primitive | T | T* | - (1) | - (1) | -| Object | T | T* | T | T* | - -#### Rules For Parameters Of Primitive-Type - -(1) A primitive-type cannot be consumed or produced because it's always statically allocated. - -### Update - -The caller has to allocate memory for `T*`. -The callee is allowed to mutate the memory pointed to by `T*`. -The caller is responsible to free the memory pointed to by `T*`. - -#### Rules For Parameters Of Object-Type - -##### Read - -The caller has to guarantee that either-or: - -* `T` is `NULL` -* `T` is pointing to a valid object of type `*T` (allocated as defined under 'Rules For Parameter Allocation') - This guarantee applies transitively for all object-type members of `*T`. - -The callee is not allowed to mutate or free any memory that can be reached through `T`. -The caller is responsible to free all the memory that can be reached through `T`. - -##### Update - -The caller has to guarantee that: - -* All object-types reachable through `T*` are either `NULL` or pointing to a valid object - (allocated as defined under [Rules For Parameter Allocation](#rules-for-parameter-allocation)) - -The callee is allowed to mutate the object in two ways: - -1. Mutate any primitive-types reachable through `T*` -2. Free or replace any object-types reachable trough `T*` - -The callee has to guarantee, that upon return of the method: - -* `T*` is pointing to a valid `*T` (allocated as defined under [Rules For Parameter Allocation](#rules-for-parameter-allocation)) -* All object-type members reachable through `T*` are either `NULL` or pointing to a valid object of type `*T` (allocated as - defined under [Rules For Parameter Allocation](#rules-for-parameter-allocation)) - -Upon success of the method call: -The caller must replace all pointers to `*T` and to any of its transitive members by dereferencing `T*` and its respective -transitive members. -The caller must free `T` and any of its transitive members. - -TODO: Upon any failure of the method call: - -##### Consume - -The same rules for mode `Read` apply, with the exception that the caller has to guarantee to never access `T` again in -any way. - -##### Produce +'C' because the syntax and some concepts are based on the C language. -The caller is allowed to pass a `T*` with an undefined value. -TODO... +A concrete interface and client code using the interface can be generated +for any language where there exist a language mapping for. -#### Rules For Multithreading +A language mapping consists of: +* A language mapping specification (lms) +* An interface generator (ig) -These rules apply to all memory that can be accessed through a parameter. -Such memory must be allocated in the calling thread No such memory can be shared with other -TODO.... +# pEp-IDL +The pEp interface description language +... diff --git a/lm-c99/lms-c99.md b/lm-c99/lms-c99.md new file mode 100644 index 0000000..ddf47d8 --- /dev/null +++ b/lm-c99/lms-c99.md @@ -0,0 +1,237 @@ +# pEpACIDLang - Language Mapping Specification for C99 (LMS-C99) + + +* [pEpACIDLang - Language Mapping Specification for C99 (LMS-C99)](#pepacidlang---language-mapping-specification-for-c99-lms-c99) + * [About This Document](#about-this-document) + * [IDL-Types](#idl-types) + * [Type Classes](#type-classes) + * [IDL-Type Mapping To C](#idl-type-mapping-to-c) + * [Creation and Destruction](#creation-and-destruction) + * [Primitive Types](#primitive-types) + * [Object Types](#object-types) + * [Allocators](#allocators) + * [Destructors](#destructors) + * [Method Parameters](#method-parameters) + * [Rules For Parameter Allocation](#rules-for-parameter-allocation) + * [Parameter Passing Modes](#parameter-passing-modes) + * [Mapping Table for C](#mapping-table-for-c) + * [Rules For Parameters Of Primitive-Type](#rules-for-parameters-of-primitive-type) + * [Update](#update) + * [Rules For Parameters Of Object-Type](#rules-for-parameters-of-object-type) + * [Read](#read) + * [Update](#update-1) + * [Consume](#consume) + * [Produce](#produce) + * [Rules For Multithreading](#rules-for-multithreading) + + +This is the document specifying the pEpACIDLang language mapping for C99. + +C99, because this is the minimum language level for the generated target code. +We will use features of a higher language level once there are good reasons to do that. + +The interface generator implements parts of the language mapping specification. + + +## About This Document + +State: Draft, to be reviewed with fdik and positron. + +**ATTENTION, IMPORTANT** +In this document, all types expressed as T are the IDL-types, not their corresponding c-types. +An example for clarity: +If `T` is the type `string`, the IDL-type `string` is meant, so the c-type of `T*` is `char**`. + +Usually a variable typename is expressed as `T`. But sometimes `T` is being used to refer to an instance of type `T`. +This imprecision is used for brevity, but only where the context does not allow for an ambiguity. + +## IDL-Types + +### Type Classes + +There are only two type-classes. + +* Primitive Types +* Object Types + +### IDL-Type Mapping To C + +| Type-Class | IDL-Type | C-Type | +|------------|-----------|--------------| +| Primitive | int | int | +| Primitive | uint | unsigned int | +| Primitive | size | size_t | +| Primitive | bool | bool | +| Primitive | enum | enum | +| Object | struct | struct* | +| Object | string | char* | +| Object | binary | char* | +| Object | opaque | void* | +| Object | list\ | list_T* | +| Object | pair | pair_F_S* | + +### Creation and Destruction + +#### Primitive Types + +* Primitive types are always statically allocated +* Primitive types are trivially constructable and destroyable +* All storage classes (auto/static/extern/register) are allowed + +#### Object Types + +For any object-type `T`, corresponding `new` and `free` methods are being generated. + +To create an object of type `T` correctly, there are two ways: + +1. Using its allocator-method +2. Using any method that has a parameter of type `T` with mode `Produce` + +To destroy an object of type `T` correctly, the only way is to use its destructor-method. + +##### Allocators + +The allocator-method has the signature: +`IDL_STATUS new_T(T*)` + +* The memory for `T` has to be dynamically allocated +* An empty object is being created. Any object-types reachable through `T` are pointing to `NULL`. + +Result: +STATUS_OK - `T*` is pointing to a valid object +STATUS_ERROR - Dereferencing of `T*` is undefined behaviour + +##### Destructors + +The destructor-method has the signature: +`IDL_STATUS free_T(T*)` + +1. For all object-type members of `T` itself, their respective destructor-methods are being called +2. The memory for `T` is freed compatibly to how it was allocated using its allocator-method +3. `T*` is set to `NULL` + +Result: +STATUS_OK - All memory reachable through `T*` is freed and `T*` is NULL +STATUS_ERROR - FATAL (most implementations of `free()` can guarantee this will never happen) + +## Method Parameters + +The main concerns when sharing memory (e.g. in form of parameters) are: + +* Ownership: defined as who is allowed and responsible to destroy an object. +* Mutability: Who is allowed to change the contents of the memory location that is known to several parties. + +In environments where memory management is explicit, the lifecycle of data in memory is: + +1. Memory being allocated +2. Memory being shared with producers/consumers (e.g. as a parameter Read/Update/Consume) +3. Read/write operations by multiple parties (needs synchronization if multithreaded environment) +3. Make sure this memory will never be accessed again by nobody +4. Memory has to be freed exactly once and compatibly to how it was allocated + +Every such lifecycle must be completed. +All of this must be guaranteed. + +### Rules For Parameter Allocation + +Parameters have to be allocated as follows: + +* Primitive-types: The general rules outlined under [Creation and Destruction](#creation-and-destruction) apply +* Object-types: Using the allocator- and destructor-methods outlined under [Creation and Destruction](#creation-and-destruction) + +These rules apply regardless of the parameter passing mode. + +### Parameter Passing Modes + +The modes are named by describing what the callee does, from the perspective of the callee, using one verb. + +* `Read` - Immutable, ownership remains with caller +* `Update` - Mutable, ownership remains with caller +* `Consume` - Mutable, ownership goes to callee +* `Produce` - Immutable, ownership goes to caller + +#### Mapping Table for C + +Type of `T` as a function of type-class and mode. +Where `T` any of the respective IDL-Types (not their respective c-type, as mentioned in [About This Document](#about-this-document)). + +| Mode/Type-Class | READ | UPDATE | CONSUME | PRODUCE | +|------------------|------|--------|---------|---------| +| Primitive | T | T* | - (1) | - (1) | +| Object | T | T* | T | T* | + +#### Rules For Parameters Of Primitive-Type + +(1) A primitive-type cannot be consumed or produced because it's always statically allocated. + +### Update + +The caller has to allocate memory for `T*`. +The callee is allowed to mutate the memory pointed to by `T*`. +The caller is responsible to free the memory pointed to by `T*`. + +#### Rules For Parameters Of Object-Type + +##### Read + +The caller has to guarantee that either-or: + +* `T` is `NULL` +* `T` is pointing to a valid object of type `*T` (allocated as defined under 'Rules For Parameter Allocation') + This guarantee applies transitively for all object-type members of `*T`. + +The callee is not allowed to mutate or free any memory that can be reached through `T`. +The caller is responsible to free all the memory that can be reached through `T`. + +##### Update + +The caller has to guarantee that: + +* All object-types reachable through `T*` are either `NULL` or pointing to a valid object + (allocated as defined under [Rules For Parameter Allocation](#rules-for-parameter-allocation)) + +The callee is allowed to mutate the object in two ways: + +1. Mutate any primitive-types reachable through `T*` +2. Free or replace any object-types reachable trough `T*` + +The callee has to guarantee, that upon return of the method: + +* `T*` is pointing to a valid `*T` (allocated as defined under [Rules For Parameter Allocation](#rules-for-parameter-allocation)) +* All object-type members reachable through `T*` are either `NULL` or pointing to a valid object of type `*T` (allocated as + defined under [Rules For Parameter Allocation](#rules-for-parameter-allocation)) + +Upon success of the method call: +The caller must replace all pointers to `*T` and to any of its transitive members by dereferencing `T*` and its respective +transitive members. +The caller must free `T` and any of its transitive members. + +TODO: Upon any failure of the method call: + +##### Consume + +The same rules for mode `Read` apply, with the exception that the caller has to guarantee to never access `T` again in +any way. + +##### Produce + +The caller is allowed to pass a `T*` with an undefined value. +TODO... + +#### Rules For Multithreading + +These rules apply to all memory that can be accessed through a parameter. +Such memory must be allocated in the calling thread No such memory can be shared with other +TODO.... + + + + + + + + + + + +