Module ddsl
DDSL Core Abstraction; see ddsl.xtypes for a concrete implementation.
Core primitives for the Datatype definition Domain Specific Language (DDSL). Defines and implements the DDSL meta-model. The core abstractions are:
- datatype (a.k.a. datamodel or model)
- instance
- collection
- alias
- qualifier
These primitives can be used to define datatypes according to a set of datatype construction rules (for example, ddsl.xtypes). Thus, DDSL can be thought of as a meta-model class implementing the semantic data definition model underlying OMG X-Types.
The DDSL core engine provides the infrastructure to create instances and instance collections backed by datatypes, to manipulate the underlying datatypes, keep all the instances in sync with the underlying datatypes.
A datatype is a blueprint for a data structure. Any
number of data-objects or instances (a.k.a. xinstance
) can be created
from a datatype. Every instance is backed by an underlying datatype. The
underlying datatype is never exposed directly; it is always manipulated
through any one of its instances. Thus, any instance can used as a handle
to manipulate the underlying datatype. Any changes made to the underlying
datatype are propagated to all its instances---thus keeping all the
instances in "sync" with the underlying datatype.
Any instance can be used as a constructor for new instances of the underlying
datatype---when used in this manner, an instance can be thought of as a
template for creating new instances. More specifically, we refer
to the instance returned by a datatype constructor as the template instance
(a.k.a. xtemplate
) for that datatytpe. It is used as the
cannonical template instance for creating other instances of the datatype,
and as the handle for manipulating the datatype. Its fields should not be
altered, as they are used to initialize the fields of new instances
created from it.
Nomenclature
This documentation uses the following nomenclature to refer to parts of a datatype. Below, the nomenclature is illustrated using an IDL example.
// @AnnotationX (annotations are 'qualifiers') struct Model { // Datatype Element1 role1; // @AnnotationY (a 'qualifier') Element2 role2; // sequence<Element3> role3;// a one-dimensional 'collection' Element4 role4[7][9] // a multi-dimensional 'collection' }
where ElementX
may be recursively defined as another Model (i.e. datatype)
composed of other elements.
To create an instance (xinstance
) named i1
from a datatytype
named Model
:
local i1 = new_instance(Model, 'i1')
Now, one can use all the fields of the resulting table, i1
. Furthermore,
the fields are properly initialized for indexing into a storage scheme based
on flattening out the field names.
i1.role1 == 'i1.role1'
More precisely, a newly created xinstance
(and, therefore also the
xtemplate
) will have the fields initialized as follows.
- For a primitive (i.e. atomic) member role:
role = 'role'
- For a composite member role:
roleX = new_instance(ElementX, 'roleX')
- For a collection member role (sequences or arrays):
roleY = new_collection(ElementY, capacity, 'roleY')
Info:
- Author: Rajive Joshi
Functions
kind (instance) | Get the datatype kind for any arbitrary object. |
template (instance) | Retrieve the (cannonical) template instance. |
resolve (template) | Resolve an alias template to the underlying non-alias template and the collection qualifiers that wrap that non-alias template. |
nsname (template[, namespace=nil]) | Qualified (scoped) name of a datatype model relative to a namespace. |
nsroot (template) | Get the root namespace (the outermost enclosing scope) for an instance. |
is_collection (v) | Is the given object a collection of instances? |
Tables
EMPTY | Initializer/sentinel value to indicate an empty datatype definition. |
Fields
log | logger to log messages and get/set the verbosity levels. |
Attributes
KIND () | Immutable data(type) model kind. |
NAME () | Name of the data(type) model. |
NS () | Namespace a data(type) model belongs to. |
QUALIFIERS () | Qualifiers associated with a data(type) model. |
Constructors
new_instance (template[, name=nil[, is_role_instance=nil]]) | Create an instance, using another instance as a template. |
new_collection (content_template[, capacity=nil[, name=nil[, is_role_instance=nil]]]) | Creates a new named collection of instances based on an element template. |
Functions
- kind (instance)
-
Get the datatype kind for any arbitrary object.
Parameters:
- instance xinstance the object for which to retrieve the model type
Returns:
-
the datatype KIND or nil (if 'value' is not a valid datatype)
- template (instance)
-
Retrieve the (cannonical) template instance.
The instance would have been created previously using new_instance() or
new_collection() or
new_template
().Parameters:
- instance xinstance the instance whose template we want to retrieve
Returns:
-
xtemplate
the underlying template (cannonical) instance
- resolve (template)
-
Resolve an alias template to the underlying non-alias template and the
collection qualifiers that wrap that non-alias template.
Parameters:
- template xinstance the alias datatype template to resolve
Returns:
-
...
variadic number of return values consisting of the underlying non-alias datatype template, and the collection qualifiers wrapping it
[ [collection_qualifier,] ... ] <Non-Alias Template>
- nsname (template[, namespace=nil])
-
Qualified (scoped) name of a datatype model relative to a namespace.
Computes the shortest distance (scoped name) to navigate to the datatype template from namespace. Each name segment is separated by '::'.Parameters:
- template xinstance the datatype whose qualified name is desired in the context of the namespace
- namespace
xtemplate
the namespace datatype; if nil, defaults to
template's outermost enclosing scope (
root
namespace) (default nil)
Returns:
-
string
the qualified name of the datatype relative to the
namespace; may be nil (for example when template == namespace).
- nsroot (template)
-
Get the root namespace (the outermost enclosing scope) for an instance.
Note that a namespace without an enclosing namespace is the outermost
enclosing scope.
Parameters:
- template xinstance the instance (or template) whose root is to be determined
Returns:
-
xtemplate
the root namespace ie. the outermost enclosing scope
(NOTE: maybe template itself)
- is_collection (v)
-
Is the given object a collection of instances?
Parameters:
- v xinstance the object to check
Returns:
-
boolean or nil
true if v is a collection, false or nil otherwise
Tables
Fields
- log
-
logger to log messages and get/set the verbosity levels.
This module extends the logger to add a
version
field.Usage:
-- show version print(ddsl.log.version)
Attributes
Every xinstance
has a metatable that implements the following attributes.
For example, if the metatable, model
defines the datatype
model, then the KIND table key specifies the kind of datatype model.
model[KIND] = <the datatype model kind>
- KIND ()
- Immutable data(type) model kind. Cannot be changed after a datatype model is constructed.
- NAME ()
- Name of the data(type) model.
- NS ()
- Namespace a data(type) model belongs to.
- QUALIFIERS ()
- Qualifiers associated with a data(type) model.
Constructors
- new_instance (template[, name=nil[, is_role_instance=nil]])
-
Create an instance, using another instance as a template.
Parameters:
- template xtemplate the template to use for creating an instance
- name
string
the template role name; maybe nil
- non-nil => creating a cannonical template instance
- nil => creating an instance for holding data
- is_role_instance
bool
is the new instance going to be a part of
a role instance, i.e. will the new instance belong to a
xtemplate
? (default nil)
Returns:
-
xinstance
newly created instance that supports indexing by
name
Usage:
-- As an index into some storage system: sample[] local myInstance = ddsl.new_instance(MyType, "myInstance") local member = sample[myInstance.member] -- = sample["myInstance.member"] -- As storage for data itself local myInstance = ddsl.new_instance(MyType) myInstance.member = "value"
- new_collection (content_template[, capacity=nil[, name=nil[, is_role_instance=nil]]])
-
Creates a new named collection of instances based on an element template.
The collection is comprised of elements specified by the given template or collection (previously created via a call to this function). Note that a sequence or array field in an instance is also a collection of instances (created using this constructor).Parameters:
- content_template
xtemplate
the collection element element datatype template
- may be a template i.e.
xtemplate
(i.e. a non-collection) OR - may be a collection (i.e. creating a collection of collections)
- may be a template i.e.
- capacity the capacity, i.e. the maximum number of instances; nil => unbounded (default nil)
- name
string
role name, if the new instance will be a member of another instance.
- non-nil => creating a template instance
- nil => creating an instance for holding data
- is_role_instance bool is the new collection going to be part of a role instance, i.e. will it belong to a template? (default nil)
Returns:
-
xinstance
returns the newly created collection instance
Usage:
-- As an index into DDS dynamic data: sample[] local myInstance = ddsl.new_collection(MyType, 10, "myInstance") for i = 1, sample[#myInstance] do -- = sample['myInstance#'] -- access the i-th element print(sample[myInstance[i].member]) -- = sample["myInstance[i].member"] end -- As a storage for data itself local myInstance = ddsl.new_collection(MyType, 10) for i = 1, 5 do print(myInstance[i].member) -- get the i-th element = "member" myInstance[i].member = i -- set the i-th element end -- the actual number of elements print(#myInstance) -- 5 -- the collection capacity print(myInstance()) -- 10
- content_template
xtemplate