diff --git a/examples/Makefile b/examples/Makefile index 12ebc14..ff2b9d0 100644 --- a/examples/Makefile +++ b/examples/Makefile @@ -5,7 +5,7 @@ TARGET_XML+=interface_example1.xml -.PHONY: all yml clean +.PHONY: all xml clean all: c_interface $(TARGET_XML) diff --git a/examples/interface_example1.yml2 b/examples/interface_example1.yml2 index 061f109..fa425f2 100644 --- a/examples/interface_example1.yml2 +++ b/examples/interface_example1.yml2 @@ -1,84 +1,127 @@ -include pEpACIDLang.yml2 - -package pkg { - 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; - - enum enum1 { - item item1 doc="oneline doc"; - item item2 doc=""; - item item3 - doc= - """ - item 3 - ------ - multiline - doc - """; - }; +pEpACIDLang { + include pEpACIDLang.yml2 - enum enum2 { - item item1 0; - item item2 1; - item item3 2 - doc= - """ + package example { + version 1.0; + license "License text"; + copyleft "Copyleft text"; + api api1 { + // 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; + enum enum1 { + item item1 doc="item with automatic value"; + item item2 23 doc="item with explicit value"; + hex item3 0xff + doc= + """ + hex enum item + ------------- + use 'hex' instead of 'item' + and specify value as 3rd param + """; + }; - item 3 - ------ + struct struct1 { + field int int1; + field size size1 doc="short doc"; + field string string1 + doc=""" + Multiline + Doc + """; + }; - multiline - doc with bad formattting """; - }; - enum enum3 { - hex item1 0x00; - hex item2 0x10 doc="oneline doc"; - hex item3 0xff - doc= - """ - item 3 - ------ - multi line - doc - """; - }; + // Param Passing Modes + // * borrow + // * mborrow + // * claim + // * provide - struct struct1 { - field int int1; - field size size1 doc="short doc"; - field string string1 - doc=""" - Multiline - Doc - """, - bla="fds"; - }; - }; + // TEST + // ---- + // Test comma after param + + method test_one_param { + param borrow size p + doc=""" + Multiline + Doc + """; + }; + + method test_two_param { + param borrow size p1 + doc=""" + Multiline + Doc + """; + param borrow size p2 + doc=""" + Multiline + Doc + """; + }; + + + + // TEST + // ---- - api api2 { + 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; + }; +}; \ No newline at end of file diff --git a/idl/pEpACIDLang.yml2 b/idl/pEpACIDLang.yml2 index e9aabe1..548af1e 100644 --- a/idl/pEpACIDLang.yml2 +++ b/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 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 \ No newline at end of file +//decl create @type @name (mode=create) alias parm; + +// decl throws @except; +// decl caveat(mode=caveat) alias doc; + + diff --git a/lm-c99/ig-c99.ysl2 b/lm-c99/ig-c99.ysl2 index 937450a..d6e6366 100644 --- a/lm-c99/ig-c99.ysl2 +++ b/lm-c99/ig-c99.ysl2 @@ -3,13 +3,171 @@ 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"; @@ -24,16 +182,16 @@ tstylesheet { // «$pkg_copyleft» #pragma once + #ifdef __cplusplus extern "C" { #endif - #include - //#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 // ---