EPICS Home

Experimental Physics and Industrial Control System


 
2002  2003  2004  2005  <20062007  2008  2009  2010  2011  2012  2013  2014  2015  2016  2017  2018  2019  2020  2021  2022  2023  2024  Index 2002  2003  2004  2005  <20062007  2008  2009  2010  2011  2012  2013  2014  2015  2016  2017  2018  2019  2020  2021  2022  2023  2024 
<== Date ==> <== Thread ==>

Subject: DBD Syntax (Arrays)
From: Benjamin Franksen <[email protected]>
To: [email protected]
Date: Mon, 6 Feb 2006 15:52:11 +0100
Hello All,

The current proposal for the definition of array fields in structs and 
records [1] seems more complicated than necessary to me, while being in 
some cases not expressive enough. I would like 
to propose some simplifications and one addition.

I first describe my proposal and how it differs from the current 
proposal. I will give detailed rationale below.

Proposal
========

1. Remove capacity declarations.

The current proposal allows array field declarations to fix a capacity 
(or more than one capacity, for multi-dimensional arrays). I propose to 
remove this from the dbd syntax. The current proposal for record 
instance syntax already provides for setting capacities in addition to 
initialization of array elements.

2. Disallow un-specified (variable) dimension.

The current proposal allows to leave the array's dimension un-specified. 
I propose to forbid this.

Proposals (1) and (2) can be viewed and judged independent from the 
following (3), (4) and (5). It is debatable whether (5) is very useful, 
but if it is not and (3) is adopted, than (4) is a necessity, I think.

3. Disallow un-specified base type.

The current proposal allows to leave the type of the elements of an 
array unspecified. I propose to disallow this. See proposals (4) or 5) 
for a replacement.

4. Allow field types to be type variables.

I propose to allow struct and record declarations to specify one or more 
type variables, over which the struct or record is parameterized. Type 
variables that have been declared as parameters to a struct or record 
may be used by subordinate field declarations everywhere a field type 
is expected. Type variables must be instantiated (a) when defining a 
record instance and (b) when a struct is used as a field type (in this 
case, possibly with another type variable).

5. Add type 'any' to use for scalar fields as well as array base types.

I propose to add a base type 'any' that represents a union of all the 
simple scalar types, i.e. all of {octet, bool, int16, int32, int64, 
float32, float64, string}.

The resulting syntax is a lot simpler; the field type of an array field 
always has the form:

	array(dimension,baseType)

where
	dimension:	a positive integer, giving the array's dimension
	baseType:	type of the array's elements

Examples:

field type of 1-dimensional array of doubles
	array(1,float64)

field type of 3-dimensional array of strings
	array(3,string)

I propose to use angular brackets <a,b,c,...> for specifying type 
parameters and arguments, as familiar from C++ 'templates' and Java 
'generics'. Examples:

field type of 2-dimensional array of structs of type displayLimit<a>, 
where type variable 'a' is instantiated to 'int32'
	array(2,struct(displayLimit<int32>))

field declaration of 1-dimensional array of structs of type 
displayLimit<a> where type variable 'a' is instantiated to anotehr type 
variable 'b'
	field(my2dimLimits, array(1,struct(displayLimit<b>)))

field declaration of a scalar field of type 'a' (which must be a 
parameter to the surrounding struct or record):
	field(x,a)

Declaring type parameters:

I propose that type parameters are specified like this

	struct(name)<type-parameters> {
		field...
	}

resp.

	record(name)<type-parameters> {
		field...
	}

where 'type-parameters' is a comma separated list of identifiers. Type 
variables scope over the following {}-delimited block. It may be useful 
to classify field types into categories such as 'scalar', 'number', 
'integral', and 'floating', in order to allow type variables to be 
constrained to belong to one of these categories. This could be done 
using a syntax like

	struct(name)<a:numeric, b:integral, c:scalar> {...}

with the following (predefined) categories:

	integral = {int16, int32, int64}
	floating = {float32, float64}
	numeric = integral U floating
	scalar = {octet, bool, string, any} U numeric

(where 'U' means 'set union'). Constraints propagate outwards, e.g. if 
we have struct(displayLimits)<a:numeric> then every instantiation must 
be constrained to 'numeric' or a subset thereof (including a concrete 
element of 'numeric'). In particular, an unconstrained type variable 
cannot be used as argument to a constrained type parameter. (These are 
just the minimal conditions under which the system is sound). Note: I 
am /not/ proposing that the user can add new categories. There will 
only be a handfull of predefined ones.

To support instantiation of type variables at the record instance level, 
the record instance syntax [2] must be extended like this:

	waveform<float64> foo:bar:wave = {
		...
	}

Of course, the angular brackets can be left out in all cases where there 
are not type variables to be declared or instantiated.

Rationale
=========

1. Remove capacity declarations.

I just don't see any justification for this. I would be very much 
surprised if anyone can come up with an example of a record or struct 
where it is /better/ to fix capacities statically for all times, as 
opposed to dynamically, either at init time or at even during runtime. 
The possibility to restrict the capacity from the outset reminds me of 
the trouble we had in all existing EPICS version with string sizes that 
had to be fixed in the record definition. Also, I can't see any 
advantage for efficiency, since memory allocation for arrays has to be 
dynamic anyway.

2. Disallow un-specified (variable) dimension.

Same as (1): I have great difficulties to imagine a real-world example 
where this is useful or even necessary. Even in case someone actually 
comes up with a convincing example, this could most probably be solved 
by using separate fields for each possible dimension (i.e. one field 
for 1-dimensional array, another for 2-dimensional, etc..); note that 
memory overhead is insignificant for array fields that are not used 
(i.e. with zero capacity).

3. Disallow un-specified base type.
4. Allow field types to be type variables.

These proposals actually belong together. My rationale is that this is 
what the user really wants! There are very few situations where it 
makes sense to have the type of a record field change at runtime. In 
almost all cases, we really want to have the field types (whether array 
or scalar) fixed at runtime, but nevertheless want to decide /per 
record instance/ what the actual type will be. For structs, what we 
want is to create generic re-usable building blocks for records (see 
[3]). This is going to be an error-prone and annoyingly repetitive 
exercise whithout the possibility to parameterize over field types.

5. Add type 'any' to use for scalar fields as well as array base types.

The rationale for this is that /if/ we think we must support field types 
that change at runtime (which is, IMO, open to debate), then it is 
inconsistent to allow this only for arrays and not for scalars, thereby 
introducing additional syntax that applies only for arrays. The 
additional type 'any' would solve the problem in a more systematic way 
with no extra case for arrays (e.g. array(1,any) would be a valid field 
type).

A last remark: I have deliberately not said anything about 
implementation, in order to focus first on what we want, and also 
because this message is already quite long. That said, I don't believe 
implementation will cause great difficulties, even in languages that do 
not have the concept of type variables built in, such as C. (Remember 
that most of the code will be generated anyway.)

[1]http://www.aps.anl.gov/epics/wiki/index.php/V4_DBD_Statement_Syntax

[2]http://www.aps.anl.gov/epics/wiki/index.php/V4_DB_Record_Instance_Syntax

[3]http://www.aps.anl.gov/epics/wiki/index.php/V4_Design:_Assembling_Record_Support

Ben

Replies:
Re: DBD Syntax (Arrays) Marty Kraimer

Navigate by Date:
Prev: Re: mallocMustSucceed( 0 ) non-portable Benjamin Franksen
Next: Re: DBD Syntax (Arrays) Marty Kraimer
Index: 2002  2003  2004  2005  <20062007  2008  2009  2010  2011  2012  2013  2014  2015  2016  2017  2018  2019  2020  2021  2022  2023  2024 
Navigate by Thread:
Prev: Re: mallocMustSucceed( 0 ) non-portable Benjamin Franksen
Next: Re: DBD Syntax (Arrays) Marty Kraimer
Index: 2002  2003  2004  2005  <20062007  2008  2009  2010  2011  2012  2013  2014  2015  2016  2017  2018  2019  2020  2021  2022  2023  2024