Until I can spec this out properly, I’ll just quote from “Unwanted Software Thoughts Syndrome”
Type Interface Definition Language (TIDL)
Originally I wrote:
An IDL that is essentially the datatype and interface parts of the full Teufel language, with an accompanying code generator. It will generate stub and skeleton code in C much like CORBA. An extension will generate skeleton code for modules in Ruby, Lua, Python, and other scripting languages, not unlike SWIG.
Instead of a Teufel language, however, it will generate C libraries using memory management under the hood but usable in C’s grab-bag of memory techniques (malloc/free, stack allocation, refcounting, etc.)
Later I wrote:
… language and parser for generating stub code in a hybrid function-oriented/object-oriented multiprocess component model …
The result will probably closely resemble XIDL, originally for
Exported Objects.
Ideally the only difference is whether the code generated has EAny
refcounting APIs or MPool
APIs. The two projects could be unified
with a simple switch, assuming I implemented both.1
The full language will include the assertion language CDL. Implementing assertions becomes much easier when one is also generating the skeletons and stubs on both ends.
XIDL
Taking some inspiration from XPCOM, one could introduce an Interface Definition Language to more easily define interfaces, declare classes, and generate function skeletons. A tool could even take an IDL representation, parse the C header files for a library, and output a complete wrapper for that library.
Informal Syntax
Rather than mimic CORBA IDL or C/C++, XIDL would represent how functions really operate across thread and process boundaries.
For example, here’s one possible function to get a substring from a string.
function substring(s: String, start: int, stop: int)
=> (ss: String, indexes_ok: boolean)
In the ExO runtime functions can return multiple results.2
Here the second result returns whether the indexes indicated a proper substring
or whether start
indicated a character after stop
.
In cases where there’s only one return value one can use this syntax:
function substring(s: String, start: integer, stop: integer) => String
If there’s no return value, a function (typically called a procedure) can simply omit an arrow entirely:
function set_char_at(s: Char_Buffer, index: int, value: char)
A small but complete XIDL file might look like this:
module exo.util.string is
interface Char_Sequence is
char_at(i: int) => char
length => integer
slice(start: int, stop: int)
=> (result: Char_Sequence, indexes_ok: boolean)
slice_from(start: int)
=> (result: Char_Sequence, indexes_ok: boolean)
slice_to(stop: int)
=> (result: Char_Sequence, indexes_ok: boolean)
to_chars: [char]
end
class Char_Buffer : Char_Sequence is
+ new
+ new_copy(s: Char_Sequence)
+ new_with_chars(wcs: [char])
- append(c: Char_Sequence)
- append_all(cs: [Char_Sequence])
- set_char_at(i: int, value: char)
- to_string => String
end
class String : Char_Sequence is
+ empty
+ for_char(c: char)
+ new(s: Char_Sequence)
+ new_with_ascii(b: [octet])
+ new_with_chars(wcs: [char])
+ new_with_encoding(e: Symbol, b: [octet])
+ new_with_utf8(b: [octet])
- encoding => symbol
end
function compare(a: Char_Sequence?, b: Char_Sequence?) => int
function join(a: Char_Sequence, b: Char_Sequence) => String
function join_all(args: [Char_Sequence]) => String
end
[
x]
means ‘List of` x.
The syntax to specify Records and Tuples is to be determined.
Note that all “features” of an interface have their receiver
as an implicit first argument.
Constructors all have the implicit return value of a class instance.
Also, no argument may be null
unless the type is marked with a ?
.
Formal Syntax
TODO
-
My plan was to find out if MPool was feasable using MString as a test case, and fall back to Exported Objects if it wasn’t. ↩︎
-
CORBA and similar C-like syntaxes designate parameters as in, out, or inout, the latter two being translated to pointers to the data being read or written. ↩︎