Browse Source

IDL - Type System

main
heck 2 years ago
parent
commit
39cee3f467
  1. 2
      examples/Makefile
  2. 151
      examples/interface_example1.yml2
  3. 109
      idl/pEpACIDLang.yml2
  4. 335
      lm-c99/ig-c99.ysl2

2
examples/Makefile

@ -5,7 +5,7 @@
TARGET_XML+=interface_example1.xml
.PHONY: all yml clean
.PHONY: all xml clean
all: c_interface $(TARGET_XML)

151
examples/interface_example1.yml2

@ -1,84 +1,127 @@
pEpACIDLang {
include pEpACIDLang.yml2
package pkg {
package example {
version 1.0;
license "License text";
copyleft "Copyleft text";
api api1 {
// These are the idl basetypes
// They should be in the package 'pEpIdl'
// And they need to be 'imported' into every module.
// But currently there is no import/depends concept implemented
type string;
type binary;
type int;
type uint;
type size;
type bool;
type opaque;
// This is part of the API def
type stringalias is string;
// creates a type-alias with optional
// properties to specialize the type.
// the aliased type must be a basetype
deftype deftype1 as size;
deftype deftype2 as string;
deftype stringlist as list<string>;
enum enum1 {
item item1 doc="oneline doc";
item item2 doc="";
item item3
item item1 doc="item with automatic value";
item item2 23 doc="item with explicit value";
hex item3 0xff
doc=
"""
item 3
------
multiline
doc
hex enum item
-------------
use 'hex' instead of 'item'
and specify value as 3rd param
""";
};
enum enum2 {
item item1 0;
item item2 1;
item item3 2
doc=
"""
struct struct1 {
field int int1;
field size size1 doc="short doc";
field string string1
doc="""
Multiline
Doc
""";
};
item 3
------
multiline
// Param Passing Modes
// * borrow
// * mborrow
// * claim
// * provide
doc with bad formattting """;
};
// TEST
// ----
// Test comma after param
enum enum3 {
hex item1 0x00;
hex item2 0x10 doc="oneline doc";
hex item3 0xff
doc=
"""
item 3
------
multi line
doc
method test_one_param {
param borrow size p
doc="""
Multiline
Doc
""";
};
struct struct1 {
field int int1;
field size size1 doc="short doc";
field string string1
method test_two_param {
param borrow size p1
doc="""
Multiline
Doc
""",
bla="fds";
};
""";
param borrow size p2
doc="""
Multiline
Doc
""";
};
api api2 {
}
}
// TEST
// ----
method method_test_all {
// primitive basetype
param borrow size borrow_primitive_basetype;
param mborrow size mborrow_primitive_basetype;
//param claim size claim_primitive_basetype; ERROR CASE
//param provide size provide_primitive_basetype; ERROR CASE
// object basetype
param borrow string borrow_obj_basetype;
param mborrow string mborrow_obj_basetype;
param claim string claim_obj_basetype;
param provide string provide_obj_basetype;
// enum
param borrow enum1 borrow_enum;
param mborrow enum1 mborrow_enum;
//param claim enum1 claim_enum; ERROR CASE
//param provide enum1 provide_enum; ERROR CASE
// struct
param borrow struct1 borrow_struct;
param mborrow struct1 mborrow_struct;
param claim struct1 claim_struct;
param provide struct1 provide_struct;
// deftype of primitive basetype
param borrow deftype1 borrow_spec_primitive_basetype;
param mborrow deftype1 mborrow_spec_primitive_basetype;
//param claim deftype1 claim_spec_primitive_basetype; ERROR CASE
//param provide deftype1 provide_spec_primitive_basetype; ERROR CASE
// deftype of object basetype object
param borrow deftype2 borrow_spec_obj_basetype;
param mborrow deftype2 mborrow_spec_obj_basetype;
param claim deftype2 claim_spec_obj_basetype;
param provide deftype2 provide_spec_obj_basetype;
// deftype of list
param borrow stringlist borrow_spec_primitive_basetype;
param mborrow stringlist mborrow_spec_primitive_basetype;
param claim stringlist claim_spec_primitive_basetype;
param provide stringlist provide_spec_primitive_basetype;
};
};
test_types;
};
};

109
idl/pEpACIDLang.yml2

@ -6,12 +6,66 @@
// written by Volker Birk and Nana Karlstetter
// typekind
// --------
// typekinds are all idl defined
// typekinds can be used to create user defined types
// a basetype can be specialized
// an enum-type can be defined using items
// a struct-type can be defined using fields
// a list can be defined holding a type T, where T can be any defined type
// types
// -----
// types are either:
// * idl-defined
// * basetypes
// * user-defined
// * deftype
// * enum
// * struct
// * list
// * undefined
// any defined type can be instantiated.
// Generic types
// generic typeskinds list, pair, set
// can only be used to define types
// they can not be used as types (e.g. in params, fields)
idl {
typekinds {
basetype;
deftype;
enum;
struct;
generics {
list;
pair;
set;
}
}
basetypes {
string; // text
// p≡p engine uses UTF-8 strings which are NFC normalized.
// Cf. https //dev.pep.foundation/Engine/Basic%20Concepts%20of%20the%20pEp%20Engine
binary; // binary data
int; // signed integer number
uint; // unsigned integer number
size; // size in memory
bool; // true or false
// timestamp; // point of time
opaque; // opaque type (was: 'any')
}
};
decl package @name;
decl api @name;
decl type @name;
decl is @type;
decl extends @type;
// deftype
decl deftype @name;
decl as @type;
// enum
decl enum @name;
@ -24,9 +78,15 @@ decl field @type @name; // optional: function=free for a free function
// method
decl method @name;
decl param @mode @type @name;
// unimplemented
//-----------------
// decl internal < field >; // internal field, p≡p engine only
// decl flag @name;
@ -34,49 +94,18 @@ decl method @name;
// decl construct, new is construct;
// readonly in parm, ownership remains with caller
decl use @type @name (mode=use) alias parm;
// decl use @type @name (mode=use) alias parm;
// inout parm, ownership remains with caller
decl supply @type @name (mode=supply) alias parm;
// decl supply @type @name (mode=supply) alias parm;
// in parm, ownership goes to callee
decl provide @type @name (mode=provide) alias parm;
// out parm, ownership goes to caller
decl return @type @name (mode=return) alias parm;
// decl provide @type @name (mode=provide) alias parm;
// factory delivers this, ownership goes to caller
decl create @type @name (mode=create) alias parm;
//decl create @type @name (mode=create) alias parm;
decl throws @except;
decl caveat(mode=caveat) alias doc;
// decl throws @except;
// decl caveat(mode=caveat) alias doc;
// base types
// string text
// p≡p engine uses UTF-8 strings which are NFC normalized.
// Cf. https //dev.pep.foundation/Engine/Basic%20Concepts%20of%20the%20pEp%20Engine
// binary binary data
// int signed integer number
// uint unsigned integer number
// size size in memory
// bool true or false
// timestamp point of time
// opaque opaque type (was: 'any')
//package idl {
// type string;
// type binary;
// type int;
// type uint;
// type size;
// type bool;
// type timestamp;
// type opaque;
//}
// collections
// list one or more elements, which have a sequence
// set one or more elements, which do not have a sequence
// pair two elements in sequence

335
lm-c99/ig-c99.ysl2

@ -3,14 +3,172 @@
include yslt.yml2
tstylesheet {
include standardlib.ysl2
template "/package", "text" {
apply "api", 0
// stdlib candidates
// -----------------
def "func:autocomma" {
result if "position()!=last()" > ,
}
def "func:exists" {
param "xpath";
choose {
when "$xpath"
result "true()";
otherwise
result "false()";
}
}
// idl-api (ysl2)
// --------------
def "func:idl_typekind_is_defined" {
param "typekind";
result "func:exists(/pEpACIDLang/idl/typekinds//*[name()=$typekind])"
}
def "func:idl_typekind_is_generic" {
param "typekind";
result "func:exists(/pEpACIDLang/idl/typekinds/generics/*[name()=$typekind])"
}
def "func:idl_type_is_of_typekind_basetype" {
param "idltype";
result "func:exists(/pEpACIDLang/idl/basetypes/*[name()=$idltype])";
}
def "func:idl_type_is_of_typekind_deftype" {
param "idltype";
result "func:exists(//deftype[@name=$idltype])";
}
def "func:idl_type_is_of_typekind_enum" {
param "idltype";
result "func:exists(//enum[@name=$idltype])";
}
def "func:idl_type_is_of_typekind_struct" {
param "idltype";
result "func:exists(//struct[@name=$idltype])";
}
def "func:idl_type_is_of_typekind_list" {
param "idltype";
result "false()";
}
def "func:idl_type_is_defined" {
param "idltype";
choose {
when "func:idl_type_get_typekind_of_type($idltype)"
result "true()";
otherwise
result "false()";
}
}
def "func:idl_type_get_typekind_of_type" {
param "idltype";
choose {
when "func:idl_type_is_of_typekind_basetype($idltype)"
result > basetype
when "func:idl_type_is_of_typekind_deftype($idltype)"
result > deftype
when "func:idl_type_is_of_typekind_enum($idltype)"
result > enum
when "func:idl_type_is_of_typekind_struct($idltype)"
result > struct
when "func:idl_type_is_of_typekind_list($idltype)"
result > list
otherwise
result "false()";
}
}
def "func:idl_type_get_resolved_typekind" {
param "idltype";
const "idltypekind", "func:idl_type_get_typekind_of_type($idltype)";
choose {
when "$idltypekind = 'deftype'"
result "func:idl_type_get_typekind_of_type(func:idl_type_get_type_of_deftype($idltype))";
otherwise
result "$idltypekind";
}
}
def "func:idl_type_get_resolved_type" {
param "idltype";
const "idltypekind", "func:idl_type_get_typekind_of_type($idltype)";
choose {
when "$idltypekind = 'deftype'"
result "func:idl_type_get_type_of_deftype($idltype)";
otherwise
result "$idltype";
}
}
def "func:idl_type_get_type_of_deftype" {
param "idltype";
choose {
when "func:idl_type_is_of_typekind_deftype($idltype)"
result "//deftype[@name=$idltype]/as/@type";
otherwise
error > idl_resolve_deftype - is not a deftype: «$idltype»;
}
}
// typeclass is either
// * primitive
// * object
def "func:ig_c99_typeclass" {
param "idltype";
choose {
when "func:idl_type_is_defined($idltype)"
choose {
when "func:idl_type_is_of_typekind_basetype($idltype)"
result > primitive
when "func:idl_type_is_of_typekind_deftype($idltype)"
result > primitive
when "func:idl_type_is_of_typekind_enum($idltype)"
result > primitive
when "func:idl_type_is_of_typekind_struct($idltype)"
result > primitive
}
otherwise
error > ig_c99_typeclass - is not a type: «$idltype»
}
};
template "idl" document "idl_core.h", "text" {
||
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
// idl basetypes
// -------------
``apply "basetypes", 0
#ifdef __cplusplus
} // extern "C"
#endif
||
}
template "api" document "{@name}_api.h", "text" {
const "pkg_name", "../@name";
const "pkg_version", "../version/text()";
@ -24,16 +182,16 @@ tstylesheet {
// «$pkg_copyleft»
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
#include <stddef.h>
//#include "idl.h"
#include "idl_core.h"
// Types
// -----
``apply "type", 0
// deftypes
// --------
``apply "deftype", 0
// Enums
// -----
@ -43,6 +201,9 @@ tstylesheet {
// -------
``apply "struct", 0
// Functions
// ---------
``apply "method", 0
#ifdef __cplusplus
} // extern "C"
@ -51,8 +212,54 @@ tstylesheet {
}
// TYPE
// ----
// TYPE-TESTING
template "test-types" document "test_types.h", "text" {
||
// basetypes
«func:typeinfo('string')»
«func:typeinfo('binary')»
«func:typeinfo('int')»
«func:typeinfo('uint')»
«func:typeinfo('size')»
«func:typeinfo('bool')»
«func:typeinfo('opaque')»
// deftype basetype
«func:typeinfo('deftype1')»
«func:typeinfo('deftype2')»
// deftype generic
«func:typeinfo('stringlist')»
// enum
«func:typeinfo('enum1')»
// struct
«func:typeinfo('struct1')»
// undefined
«func:typeinfo('undefined')»
||
}
def "func:typeinfo" {
param "idltype";
result call "typeinfo" with "idltype", "$idltype";
};
function "typeinfo" {
param "idltype";
||
idltype: «$idltype»
idl_type_is_defined: «func:idl_type_is_defined($idltype)»
idl_type_get_typekind_of_type: «func:idl_type_get_typekind_of_type($idltype)»
idl_type_get_resolved_typekind: «func:idl_type_get_resolved_typekind($idltype)»
idl_type_get_resolved_type: «func:idl_type_get_resolved_type($idltype)»
idl_type_is_of_typekind_basetype: «func:idl_type_is_of_typekind_basetype($idltype)»
idl_type_is_of_typekind_deftype: «func:idl_type_is_of_typekind_deftype($idltype)»
idl_type_is_of_typekind_enum: «func:idl_type_is_of_typekind_enum($idltype)»
idl_type_is_of_typekind_struct: «func:idl_type_is_of_typekind_struct($idltype)»
||
}
// TYPEALIAS
// ---------
def "func:typedef" {
param "is_type";
@ -60,33 +267,59 @@ tstylesheet {
result > typedef «$is_type» «$alias_name»;\n
}
def "func:idl_basetype" {
param "idl_name";
def "func:idltype_to_ctype_basetype" {
param "idltype";
// TODO: test for is_basetype
choose {
when "$idl_name = 'string'"
result > «func:typedef('char*', $idl_name)»
when "$idl_name = 'binary'"
result > «func:typedef('char*', $idl_name)»
when "$idl_name = 'uint'"
result > «func:typedef('unsigned int', $idl_name)»
when "$idl_name = 'size'"
result > «func:typedef('size_t', $idl_name)»
when "$idl_name = 'opaque'"
result > «func:typedef('void*', $idl_name)»
when "$idltype = 'string'"
result > char*
when "$idltype = 'binary'"
result > char*
when "$idltype = 'uint'"
result > unsigned int
when "$idltype = 'size'"
result > size_t
when "$idltype = 'opaque'"
result > void*
when "$idltype = 'int'"
result > int
when "$idltype = 'bool'"
result > bool
otherwise
error > func:idltype_to_ctype_basetype - basetype not supported by ig-c99: «$idltype»
}
}
template "type" {
template "deftype" {
const "alias_name", "@name";
const "is_type", "is/@type";
const "type_or_typekind", "as/@type";
if 'string-length($is_type) > 0' {
> «func:typedef($is_type, $alias_name)»
} else {
> «func:idl_basetype($alias_name)»
choose {
when 'func:idl_typekind_is_generic($type_or_typekind)'
choose {
when "$type_or_typekind = 'list'"
> «func:typedef($type_or_typekind, $alias_name)»
otherwise
error > deftype - typekind must be generic «$type_or_typeind»
}
otherwise
choose {
when 'func:idl_type_is_of_typekind_basetype($type_or_typekind)'
> «func:typedef($type_or_typekind, $alias_name)»
otherwise
error > not a generic or basetype: «$type_or_typekind»
}
}
}
template "basetypes" {
for "*" {
const "name", "name()";
if "func:idltype_to_ctype_basetype($name) != $name" {
> «func:typedef(func:idltype_to_ctype_basetype($name), $name)»
}
}
}
@ -94,18 +327,18 @@ tstylesheet {
// ENUM
// ----
def "func:c_name_enum" {
def "func:idltype_to_ctype_enum" {
param "pkg_name";
param "name";
result "yml:ucase(concat($pkg_name, '_', $name))"
result "yml:ucase(concat($pkg_name, '_', $name))";
}
template "enum" {
const "idl_name", "@name";
const "pkg_name", "../../@name";
const "enum_name", "func:c_name_enum($pkg_name, $idl_name)";
const "enum_name", "func:idltype_to_ctype_enum($pkg_name, $idl_name)";
||
typedef enum _«$enum_name» {
``apply "item" with "enum_name", "$enum_name"
@ -122,9 +355,9 @@ tstylesheet {
apply "@doc", 0, mode="multiline";
choose {
when "@output='hex'"
| «$item_name»`if "text()" { " = 0x" value "yml:dec2hex(., 2)" }``if "position()!=last()" > ,``apply "@doc" , 0, mode="oneline"`
| «$item_name»`if "text()" { " = 0x" value "yml:dec2hex(., 2)" }`«func:autocomma()»`apply "@doc" , 0, mode="oneline"`
otherwise
| «$item_name»`if "text()" { " = " value "." }``if "position()!=last()" > ,``apply "@doc" , 0, mode="oneline"`
| «$item_name»`if "text()" { " = " value "." }``apply "@doc" , 0, mode="oneline"`
}
}
@ -133,21 +366,21 @@ tstylesheet {
// STRUCT
// ------
def "func:c_name_struct" {
def "func:idltype_to_ctype_struct" {
param "pkg_name";
param "idl_name";
result "concat(yml:capit($pkg_name), '_', yml:capit($idl_name))"
result "concat(yml:capit($pkg_name), '_', yml:capit($idl_name))";
}
template "struct" {
const "idl_name", "@name";
const "pkg_name", "../../@name";
const "c_name_struct", "func:c_name_struct($pkg_name, $idl_name)";
const "c_name", "func:idltype_to_ctype_struct($pkg_name, $idl_name)";
||
typedef struct _«$c_name_struct» {
typedef struct _«$c_name» {
``apply "field"
} «$c_name_struct»;
} «$c_name»;
||
}
@ -161,6 +394,32 @@ tstylesheet {
}
// METHOD
// ------
template "method" {
const "name", "@name";
||
PEP_STATUS «$name»(
``apply "param", 0
);
||
}
template "param" {
const "name", "@name";
const "type", "@type";
const "mode", "@mode";
|> «func:idlparam_to_cparam($type, $mode)» «@name»«func:autocomma()»
}
def "func:idlparam_to_cparam" {
param "idltype";
param "mode";
result "'sfd'";
}
// DOC
// ---

Loading…
Cancel
Save