From fe276dbc3fb92cb8784a87e64543d184bb9adac4 Mon Sep 17 00:00:00 2001 From: Joseph Wayne Norton Date: Sun, 2 Sep 2012 22:10:49 +0900 Subject: [PATCH] Align UBF's predefined and builtin types with EEP 8 --- include/ubf.hrl | 16 +- .../doc/src/ubf/misc-codes/irc_fsm_plugin.con | 6 +- priv/doc/src/ubf/misc-codes/irc_plugin.con | 14 +- .../src/ubf/misc-codes/irc_types_plugin.con | 10 +- priv/doc/src/ubf/misc-codes/ubf_b.abnf | 31 +--- .../src/ubf/misc-codes/ubf_bertrpc_plugin.erl | 15 +- priv/doc/src/ubf/ubf-user-guide.en.txt | 166 ++++++++++++------ rebar.config | 2 + src/contract_parser.erl | 35 ++-- src/contract_yecc.yrl | 4 +- src/contracts.erl | 82 +-------- src/qc_ubf_types.erl | 27 +-- src/ubf.app.src | 1 + src/ubf_client.erl | 2 +- src/ubf_plugin_meta.con | 8 +- src/ubf_server.erl | 4 +- src/ubf_types_builtin.con | 124 +++++++++++++ src/ubf_types_builtin.erl | 12 ++ src/ubf_utils.erl | 74 ++------ test/eunit/stateful_plugin.con | 2 +- test/eunit/stateless_plugin.con | 2 +- test/eunit/types_plugin.con | 8 +- test/unit/file_plugin.con | 4 +- test/unit/irc_plugin.con | 6 +- test/unit/test_plugin.con | 26 ++- 25 files changed, 385 insertions(+), 296 deletions(-) create mode 100644 src/ubf_types_builtin.con create mode 100644 src/ubf_types_builtin.erl diff --git a/include/ubf.hrl b/include/ubf.hrl index ba5e676..75a8c3c 100644 --- a/include/ubf.hrl +++ b/include/ubf.hrl @@ -32,24 +32,24 @@ %%% Macros %%%------------------------------------------------------------------- -%% @doc ubf string helper --define(S(X), - #'#S'{value=X}). - %% @doc ubf proplist helper -define(P(X), #'#P'{value=X}). +%% @doc ubf string helper +-define(S(X), + #'#S'{value=X}). + %%%------------------------------------------------------------------- %%% Records %%%------------------------------------------------------------------- -%% @doc ubf string record --record('#S', - {value="" :: string()}). - %% @doc ubf proplist record -record('#P', {value=[] :: [{term(),term()}]}). +%% @doc ubf string record +-record('#S', + {value="" :: string()}). + -endif. % -ifndef(ubf) diff --git a/priv/doc/src/ubf/misc-codes/irc_fsm_plugin.con b/priv/doc/src/ubf/misc-codes/irc_fsm_plugin.con index 737e75b..2d7363b 100644 --- a/priv/doc/src/ubf/misc-codes/irc_fsm_plugin.con +++ b/priv/doc/src/ubf/misc-codes/irc_fsm_plugin.con @@ -1,6 +1,6 @@ +NAME("irc"). -+VSN("ubf1.0"). ++VSN("ubf2.0"). +STATE start logon() => proceed() & active. %% Nick randomly assigned @@ -18,8 +18,8 @@ EVENT => changeNameEvent(). %% Nick changes name +ANYSTATE - info() => string(); - description() => string(); + info() => ubfstring(); + description() => ubfstring(); contract() => term(). diff --git a/priv/doc/src/ubf/misc-codes/irc_plugin.con b/priv/doc/src/ubf/misc-codes/irc_plugin.con index 0144a80..cb4c000 100644 --- a/priv/doc/src/ubf/misc-codes/irc_plugin.con +++ b/priv/doc/src/ubf/misc-codes/irc_plugin.con @@ -1,6 +1,6 @@ +NAME("irc"). -+VSN("ubf1.0"). ++VSN("ubf2.0"). +TYPES info() :: info; @@ -9,10 +9,10 @@ contract() :: contract; ok() :: ok; bool() :: true | false; -nick() :: string(); +nick() :: ubfstring(); oldnick() :: nick(); newnick() :: nick(); -group() :: string(); +group() :: ubfstring(); groups() :: [group()]; logon() :: logon; @@ -21,9 +21,9 @@ listGroups() :: groups; joinGroup() :: {join, group()}; leaveGroup() :: {leave, group()}; changeNick() :: {nick, nick()}; -msg() :: {msg, group(), string()}; +msg() :: {msg, group(), ubfstring()}; -msgEvent() :: {msg, nick(), group(), string()}; +msgEvent() :: {msg, nick(), group(), ubfstring()}; joinEvent() :: {joins, nick(), group()}; leaveEvent() :: {leaves, nick(), group()}; changeNameEvent() :: {changesName, oldnick(), newnick(), group()}. @@ -44,8 +44,8 @@ changeNameEvent() :: {changesName, oldnick(), newnick(), group()}. EVENT => changeNameEvent(). %% Nick changes name +ANYSTATE - info() => string(); - description() => string(); + info() => ubfstring(); + description() => ubfstring(); contract() => term(). diff --git a/priv/doc/src/ubf/misc-codes/irc_types_plugin.con b/priv/doc/src/ubf/misc-codes/irc_types_plugin.con index ef4320b..39abadb 100644 --- a/priv/doc/src/ubf/misc-codes/irc_types_plugin.con +++ b/priv/doc/src/ubf/misc-codes/irc_types_plugin.con @@ -1,6 +1,6 @@ +NAME("irc_types"). -+VSN("ubf1.0"). ++VSN("ubf2.0"). +TYPES info() :: info; @@ -9,10 +9,10 @@ contract() :: contract; ok() :: ok; bool() :: true | false; -nick() :: string(); +nick() :: ubfstring(); oldnick() :: nick(); newnick() :: nick(); -group() :: string(); +group() :: ubfstring(); groups() :: [group()]; logon() :: logon; @@ -21,9 +21,9 @@ listGroups() :: groups; joinGroup() :: {join, group()}; leaveGroup() :: {leave, group()}; changeNick() :: {nick, nick()}; -msg() :: {msg, group(), string()}; +msg() :: {msg, group(), ubfstring()}; -msgEvent() :: {msg, nick(), group(), string()}; +msgEvent() :: {msg, nick(), group(), ubfstring()}; joinEvent() :: {joins, nick(), group()}; leaveEvent() :: {leaves, nick(), group()}; changeNameEvent() :: {changesName, oldnick(), newnick(), group()}. diff --git a/priv/doc/src/ubf/misc-codes/ubf_b.abnf b/priv/doc/src/ubf/misc-codes/ubf_b.abnf index d6bdbb3..b9e45ef 100644 --- a/priv/doc/src/ubf/misc-codes/ubf_b.abnf +++ b/priv/doc/src/ubf/misc-codes/ubf_b.abnf @@ -109,23 +109,23 @@ STRING = DQUOTE *(%x20-21 / %x23-7E) DQUOTE NONEMTPYSTRING = DQUOTE 1*(%x20-21 / %x23-7E) DQUOTE -predefinedtype = ('atom' "(" [atomattrs] ")") - / ('boolean' "(" [booleanattrs] ")") +predefinedtype = ('any' "(" [anyattrs] ")") + / ('none' "(" [noneattrs] ")") + / ('atom' "(" [atomattrs] ")") / ('binary' "(" [binaryattrs] ")") / ('float' "(" [floatattrs] ")") / ('integer' "(" [integerattrs] ")") / ('list' "(" [listattrs] ")") - / ('proplist' "(" [proplistattrs] ")") - / ('string' "(" [stringattrs] ")") - / ('term' "(" [termattrs] ")") / ('tuple' "(" [tupleattrs] ")") - / ('none' "(" [noneattrs] ")") + +anyattrs = anyattr + / (anyattr *WSP "," *WSP anyattrs) + +noneattrs = *WSP atomattrs = atomattr / (atomattr *WSP "," *WSP atomattrs) -booleanattrs = *WSP - binaryattrs = binaryattr / (binaryattr *WSP "," *WSP binaryattrs) @@ -136,24 +136,11 @@ integerattrs = *WSP listattrs = listattr / (listattr *WSP "," *WSP listattrs) -proplistattrs = proplistattr - / (proplistattr *WSP "," *WSP proplistattrs) - -stringattrs = stringattr - / (stringattr *WSP "," *WSP stringattrs) - -termattrs = termattr - / (termattr *WSP "," *WSP termattrs) - tupleattrs = tupleattr / (tupleattr *WSP "," *WSP tupleattrs) -noneattrs = *WSP - +anyattr = 'nonempty' / 'nonundefined' atomattr = 'ascii' / 'asciiprintable' / 'nonempty' / 'nonundefined' binaryattr = 'ascii' / 'asciiprintable' / 'nonempty' listattr = 'nonempty' -proplistattr = 'nonempty' -stringattr = 'ascii' / 'asciiprintable' / 'nonempty' -termattr = 'nonempty' / 'nonundefined' tupleattr = 'nonempty' / 'nonundefined' diff --git a/priv/doc/src/ubf/misc-codes/ubf_bertrpc_plugin.erl b/priv/doc/src/ubf/misc-codes/ubf_bertrpc_plugin.erl index d4cddcb..cf1c8f4 100644 --- a/priv/doc/src/ubf/misc-codes/ubf_bertrpc_plugin.erl +++ b/priv/doc/src/ubf/misc-codes/ubf_bertrpc_plugin.erl @@ -9,15 +9,16 @@ %% Required (except keepalive/0) callback API for UBF stateless %% implementations. -export([info/0, description/0, keepalive/0]). +-export([moduleStart/1, moduleRestart/1]). -export([handlerStart/1, handlerStop/3, handlerRpc/1, handlerEvent/1]). -import(ubf_plugin_handler, [sendEvent/2, install_handler/2]). -compile({parse_transform,contract_parser}). --add_contract("ubf_bertrpc_plugin"). +-add_contract("src/ubf_bertrpc_plugin"). --include("ubf.hrl"). --include("ubf_plugin_stateless.hrl"). +-include_lib("ubf/include/ubf.hrl"). +-include_lib("ubf/include/ubf_plugin_stateless.hrl"). info() -> "I am a BERT-RPC server". @@ -28,6 +29,14 @@ description() -> keepalive() -> ok. +%% @doc start module +moduleStart(_Args) -> + unused. + +%% @doc restart module +moduleRestart(Args) -> + moduleStart(Args). + %% @doc start handler handlerStart(_Args) -> ack = install_handler(self(), fun handlerEvent/1), diff --git a/priv/doc/src/ubf/ubf-user-guide.en.txt b/priv/doc/src/ubf/ubf-user-guide.en.txt index f9d6e93..14fa56a 100644 --- a/priv/doc/src/ubf/ubf-user-guide.en.txt +++ b/priv/doc/src/ubf/ubf-user-guide.en.txt @@ -1,9 +1,9 @@ // -*- Doc -*- // vim: set syntax=asciidoc: -= UBF User's Guide _1st DRAFT_ -:Date: 2012/08/02 -:Revision: 0.3.7 += UBF User's Guide +:Date: 2012/09/02 +:Revision: 1.0.0 :Copyright: 2012 by Joseph Wayne Norton :Copyright: 2010-2011 Gemini Mobile Technologies, Inc. All rights reserved. :Copyright: 2002 Joe Armstrong @@ -299,14 +299,14 @@ The version of the contract is specified as a double-quoted string. ==== Types: +TYPES. -The UBF(b) type system has user-defined types and predefined types. -User-defined types and predefined types are either primitive types or -complex types. +The UBF(b) type system has user-defined types, builtin types, and +predefined types. All types are either primitive types or complex +types. The primitive types are Integer, Range, Float, Binary, String, Atom, and Reference. The complex types are Alternative, Tuple, Record, -Extended Record, and List. User-defined "complex types" are defined -recursively. +Extended Record, and List. Builtin and User-defined "complex types" +are defined recursively. ===== Definition: X() :: T @@ -402,6 +402,50 @@ A type [X1, X2, ..., Xn] is of type [T] if all of Xi are of type T. Unbounded, bounded, left unbounded, and right unbounded lists are supported. +===== Builtin: B() + +Builtin types are referenced by the notation: + +------ +B() +------ + +The name of the builtin type is 'B' and builtin types are of 2 +categories: +Erlang+ and +UBF+. The names used for builtin types are +reserved and cannot be used for user-defined types. + +Erlang builtin types are a subset of the types defined by EEP8 +<>. EEP8 types are used for authoring Erlang +types+ and ++specs+ definitions. + +|============ +| nil() | [] +| term() | any() +| boolean() | 'false' | 'true' +| byte() | 0..255 +| char() | 0..16#10ffff +| non_neg_integer() | 0.. +| pos_integer() | 1.. +| neg_integer() | ..-1 +| number() | integer() | float() +| string() | [char()] +| nonempty_string() | [char()]+ +| module() | atom() +| mfa() | {atom(), atom(), byte()} +| node() | atom() +| timeout() | 'infinity' | non_neg_integer() +| no_return() | none() +| +|============ + +UBF builtin types are types particular to UBF that can be helpful for +encoding and decoding proplists and strings. + +|============ +| ubfproplist() | {'#P', [{term(), term()}]} +| ubfstring() | {'#S', [byte()]} +|============ + ===== Predefined: P() _or_ P(A1, A2, ..., An) Predefined types are referenced by the notation: @@ -416,57 +460,48 @@ or by the notation: P(A1, A2, ..., An) ------ -The name of the predefined type is 'P'. Using the second notation, -attributes can be specified to make the predefined type less general -and thus more specific when matching objects. +The name of the predefined type is 'P'. The names used for predefined +types are reserved and cannot be used for user-defined types. + +Using the second notation, attributes can be specified to make the +predefined type less general and thus more specific when matching +objects. |============ | | ascii | asciiprintable | nonempty | nonundefined +| any | X | X | O | O +| none | X | X | X | X | integer | X | X | X | X | float | X | X | X | X | binary | O | O | O | X -| string | O | O | O | X | atom | O | O | O | O -| boolean | X | X | X | X | tuple | X | X | O | X | list | X | X | O | X -| proplist | X | X | O | X -| term | X | X | O | O -| none | X | X | X | X |============ The above table summarizes the set of supported predefined types and their respective optional attributes. -The "integer", "float", "binary", "string", "atom", "boolean", -"tuple", and "list" predefined types match directly to the -corresponding primitive or complex type. - -The "term" predefined type matches any object. - -The "proplist" predefined type is a specialized version of the "list" -predefined type that matches the following types: - ------- -[{term(), term()}] ------- +The "any" predefined type matches any object. The "none" predefined type is a placeholder to describe the return value of a function call that does not return to the caller. -The "ascii" attribute permits matches with binaries, strings, and -atoms containing only ASCII values <>. Similarly, the +The "integer", "float", "binary", "atom", "boolean", "tuple", and +"list" predefined types match directly to the corresponding primitive +or complex type. + +The "ascii" attribute permits matches with binaries and atoms +containing only ASCII values <>. Similarly, the "asciiprintable" attribute permits matches with only printable ASCII values. -The "nonempty" attribute permits matches with binaries, strings, -atoms, tuples, lists, proplists, and terms that are of length greater -than zero. The following objects would not be matched with the -"nonempty" attribute: +The "nonempty" attribute permits matches with binaries, atoms, tuples, +lists, and any that are of length greater than zero. The following +objects would not be matched with the "nonempty" attribute: ------ <<"">> -"" '' {} [] @@ -995,8 +1030,7 @@ follows: {\'proto', {\'ubf' | \'ebf' | \'jsf' | \'tbf' | \'ftbf' | atom()}}:: Enable the UBF, EBF, JSF, TBF, FTBF, or an alternative protocol wire format. Default: \'ubf'. - -{\'proto', {\'ubf' | \'ebf' | \'jsf' | \'tbf' | \'ftbf' | atom(), proplist()}}:: +{\'proto', {\'ubf' | \'ebf' | \'jsf' | \'tbf' | \'ftbf' | atom(), [atom() | tuple()]}}:: Enable the UBF, EBF, JSF, TBF, FTBF, or an alternative protocol wire format with options. Default: {\'ubf', []}. Supported options: \'safe';; @@ -1015,7 +1049,7 @@ follows: Set the starting plugin, set after a client first connects to the server. If not set, client may select the service using the startSession() API. There is no default setting. -{\'serverhello', string() | \'undefined'}:: +{\'serverhello', ubfstring() | \'undefined'}:: Meta contract greeting string, sent when a client first connects to the server. If \'undefined', server hello is not sent to the client. Default: "meta_server". @@ -1063,8 +1097,8 @@ are mandatory for all stateless plugins. ------ %% common callback API --spec info() -> string(). --spec description() -> string(). +-spec info() -> ubfstring(). +-spec description() -> ubfstring(). -spec handlerStop(Handler::pid(), Reason::term(), StateData::term()) -> NewStateData::term(). @@ -1128,10 +1162,10 @@ The above example also introduces three new concepts: - The "?S(X)" macro definition plus other helpers are located in the "ubf.hrl" Erlang header file. For Erlang, the implementation of a - UBF string is a two tuple having \'#S' as the first element and a - list of integers as the second element. A similar technique is also - used for the implementation of a UBF proplist (i.e. \'#P' and - "?P(X)). + UBF +ubfstring()+ is a two tuple having \'#S' as the first element + and a list of bytes as the second element. A similar technique is + also used for the implementation of a UBF +ubfproplist()+ + (i.e. \'#P' and "?P(X)). === Stateful @@ -1146,8 +1180,8 @@ mandatory for all stateful plugins. ------ %% common callback API --spec info() -> string(). --spec description() -> string(). +-spec info() -> ubfstring(). +-spec description() -> ubfstring(). -spec handlerStop(Handler::pid(), Reason::term(), ManagerData::term()) -> NewManagerData::term(). @@ -1257,8 +1291,37 @@ known) is returned. For TCP/IP transports, the default method is to connect to the specified host() and TCP ipport(). For the ETF transport, the alternative method is to connect to server() using the specified plugins(). The server() is either the process id or process -registered name for an already-started UBF server. See <> -for a description of options(). +registered name for an already-started UBF server. + +The list of supported options() are as follows: + +{\'clientport', ipport() | {ipport(), ipport()}}:: + Specifies the TCP port to be used by the client. If tuple format, a + port is automatically selected within the specifed range. If + \'undefined', a random port is automatically selected. Default: + \'undefined'. +{\'proto', {\'ubf' | \'ebf' | \'jsf' | \'tbf' | \'ftbf' | atom()}}:: + Enable the UBF, EBF, JSF, TBF, FTBF, or an alternative protocol wire + format. Default: \'ubf'. +{\'proto', {\'ubf' | \'ebf' | \'jsf' | \'tbf' | \'ftbf' | atom(), [atom() | tuple()]}}:: + Enable the UBF, EBF, JSF, TBF, FTBF, or an alternative protocol wire + format with options. Default: {\'ubf', []}. Supported options: + \'safe';; + Prevents decoding data that may be used to attack the Erlang + system. In the event of receiving unsafe data, decoding fails + with a badarg error. +{\'startplugin', module()}:: + Set the starting plugin, set after a client first connects to the + server. If not set, client's caller may select the service using + the startSession() API. Default: \'undefined'. +{\'serverhello', true | 'undefined'}:: + Meta contract greeting string, sent to a client when it first connects to + the server. If \'undefined', client does not expect server hello to + be sent by the server. Default: \'true'. +{\'simplerpc', boolean()}:: + Set the simple RPC mode. If \'true', client expects only the rpc + reply from the server. If \'false', server returns the rpc reply and next + state to client. Default: \'false'. The rpc/{2,3} functions make a synchronous call to the server. @@ -1571,8 +1634,8 @@ created by making a symlink to the lang-en.conf file. ------ diff -r -u 8.6.4-orig/bin/a2x.py 8.6.4/bin/a2x.py ---- 8.6.4-orig/bin/a2x.py 2011-04-24 00:50:26.000000000 +0900 -+++ 8.6.4/bin/a2x.py 2011-04-24 00:35:55.000000000 +0900 +--- 8.6.4-orig/bin/a2x.py 2011-04-24 00:50:26.000000000 +0900 ++++ 8.6.4/bin/a2x.py 2011-04-24 00:35:55.000000000 +0900 @@ -156,7 +156,10 @@ def shell_copy(src, dst): verbose('copying "%s" to "%s"' % (src,dst)) @@ -1675,6 +1738,9 @@ _Under Construction - To Be Updated_ - [[[ERLANG]]] "A general-purpose programming language and runtime environment", http://www.erlang.org. +- [[[EEP8]]] "EEP 8: Types and function specifications", + http://www.erlang.org/eeps/eep-0008.html. + - [[[GIT]]] "Fast Version Control System", http://git-scm.com. - [[[JSFCHARSET]]] "Gemini Mobile Technologies, Inc. charset module", diff --git a/rebar.config b/rebar.config index 082a03e..d4764ac 100644 --- a/rebar.config +++ b/rebar.config @@ -14,6 +14,8 @@ {erl_first_files, ["src/contract_lex.erl" , "src/contract_yecc.erl" , "src/ubf_utils.erl" + , "src/contract_parser.erl" + , "src/ubf_types_builtin.erl" ]}. %% Erlang compiler options diff --git a/src/contract_parser.erl b/src/contract_parser.erl index db27eb7..15363d1 100644 --- a/src/contract_parser.erl +++ b/src/contract_parser.erl @@ -37,7 +37,9 @@ -include("ubf_impl.hrl"). -export([parse_transform/2, - make/0, make_lex/0, make_yecc/0, preDefinedTypes/0, preDefinedTypesWithoutAttrs/0, preDefinedTypesWithAttrs/0, + make/0, make_lex/0, make_yecc/0, + preDefinedTypes/0, preDefinedTypesWithoutAttrs/0, preDefinedTypesWithAttrs/0, + builtInTypes/0, builtInTypesErlang/0, builtInTypesUBF/0, tags/1, tags/2, parse_transform_contract/2, parse_file/1 @@ -237,15 +239,19 @@ tags(P1, Imports) -> end end. -preDefinedTypes() -> preDefinedTypesWithoutAttrs() ++ preDefinedTypesWithAttrs(). +preDefinedTypes() -> + preDefinedTypesWithoutAttrs() ++ preDefinedTypesWithAttrs(). preDefinedTypesWithoutAttrs() -> - [atom, boolean, binary, float, integer, list, proplist, string, term, tuple, none]. + [any, none, atom, binary, float, integer, list, tuple]. preDefinedTypesWithAttrs() -> [ + %% any + {any,[nonempty]}, {any,[nonundefined]} + , {any,[nonempty,nonundefined]} %% atom - {atom,[ascii]}, {atom,[asciiprintable]}, {atom,[nonempty]}, {atom,[nonundefined]} + , {atom,[ascii]}, {atom,[asciiprintable]}, {atom,[nonempty]}, {atom,[nonundefined]} , {atom,[ascii,nonempty]}, {atom,[ascii,nonundefined]}, {atom,[asciiprintable,nonempty]}, {atom,[asciiprintable,nonundefined]} , {atom,[ascii,nonempty,nonundefined]}, {atom,[asciiprintable,nonempty,nonundefined]} , {atom,[nonempty,nonundefined]} @@ -254,18 +260,19 @@ preDefinedTypesWithAttrs() -> , {binary,[ascii,nonempty]}, {binary,[asciiprintable,nonempty]} %% list , {list,[nonempty]} - %% proplist - , {proplist,[nonempty]} - %% string - , {string,[ascii]}, {string,[asciiprintable]}, {string,[nonempty]} - , {string,[ascii,nonempty]}, {string,[asciiprintable,nonempty]} - %% term - , {term,[nonempty]}, {term,[nonundefined]} - , {term,[nonempty,nonundefined]} %% tuple , {tuple,[nonempty]} ]. +builtInTypes() -> + builtInTypesErlang() ++ builtInTypesUBF(). + +builtInTypesErlang() -> + [nil, term, boolean, byte, char, non_neg_integer, pos_integer, neg_integer, number, string, nonempty_string, module, mfa, node, timeout, no_return]. + +builtInTypesUBF() -> + [ubfproplist, ubfstring]. + pass2(P, Imports) -> Name = require(one, name, P), Vsn = require(one, vsn, P), @@ -273,6 +280,8 @@ pass2(P, Imports) -> Any = require(zero_or_one, anystate, P), Trans = require(many, transition, P), + AllImports = if Name =/= "ubf_types_builtin" -> [ubf_types_builtin|Imports]; true -> Imports end, + ImportTypes = lists:flatten( [ begin @@ -294,7 +303,7 @@ pass2(P, Imports) -> [ begin {TDef, TTag} = Mod:contract_type(T), {T, TDef, TTag} end || T <- TL ] end - || Import <- Imports ] + || Import <- AllImports ] ), ImportTypeNames = [ T || {T, _, _} <- ImportTypes ], diff --git a/src/contract_yecc.yrl b/src/contract_yecc.yrl index b4a4db3..c41c85a 100644 --- a/src/contract_yecc.yrl +++ b/src/contract_yecc.yrl @@ -188,11 +188,11 @@ rec_ext(Name, Args) -> if Types == [] -> [{atom,Name}, {atom,undefined}, - {predef,term}]; + {predef,any}]; true -> [{atom,Name}, eor({atom,undefined}, {tuple, [ {atom,X} || X <- Fields ]}), - {predef,term}|Types] + {predef,any}|Types] end), {record_ext, Name, Fields, Defaults, Types1}. diff --git a/src/contracts.erl b/src/contracts.erl index c26db2a..7af56ce 100644 --- a/src/contracts.erl +++ b/src/contracts.erl @@ -89,6 +89,8 @@ checkEventIn(Msg, ThisState, Mod) -> %%---------------------------------------------------------------------- %% Check type attribute +isTypeAttr(any,nonempty) -> true; +isTypeAttr(any,nonundefined) -> true; isTypeAttr(atom,ascii) -> true; isTypeAttr(atom,asciiprintable) -> true; isTypeAttr(atom,nonempty) -> true; @@ -97,12 +99,6 @@ isTypeAttr(binary,ascii) -> true; isTypeAttr(binary,asciiprintable) -> true; isTypeAttr(binary,nonempty) -> true; isTypeAttr(list,nonempty) -> true; -isTypeAttr(proplist,nonempty) -> true; -isTypeAttr(string,ascii) -> true; -isTypeAttr(string,asciiprintable) -> true; -isTypeAttr(string,nonempty) -> true; -isTypeAttr(term,nonempty) -> true; -isTypeAttr(term,nonundefined) -> true; isTypeAttr(tuple,nonempty) -> true; isTypeAttr(_,_) -> false. @@ -241,13 +237,6 @@ check_term({atom, Y}=_Check, X, _Level, _Mod) -> true -> ?FAIL({Check,X}) end; -%% boolean -check_term({boolean, Y}=_Check, X, _Level, _Mod) -> - if Y =:= X andalso is_boolean(Y) -> - true; - true -> - ?FAIL({Check,X}) - end; %% binary check_term({binary, Y}=_Check, X, _Level, _Mod) -> if Y =:= X andalso is_binary(Y) -> @@ -269,13 +258,6 @@ check_term({integer, Y}=_Check, X, _Level, _Mod) -> true -> ?FAIL({Check,X}) end; -%% string -check_term({string, {'#S', Y0}=Y}=_Check, X, _Level, _Mod) -> - if Y =:= X andalso is_list(Y0) -> - true; - true -> - ?FAIL({Check,X}) - end; %% predef check_term({predef, Args}=_Check, X, _Level, _Mod) -> case check_term_predef(Args, X) of @@ -335,10 +317,12 @@ check_term_range(Min, Max, X) -> %% check_term_predef +check_term_predef(any, _X) -> + true; +check_term_predef(none, _X) -> + true; check_term_predef(atom, X) -> is_atom(X); -check_term_predef(boolean, X) -> - is_boolean(X); check_term_predef(binary, X) -> is_binary(X); check_term_predef(float, X) -> @@ -347,54 +331,19 @@ check_term_predef(integer, X) -> is_integer(X); check_term_predef(list, X) -> is_list(X); -check_term_predef(proplist, X) -> - case X of - {'#P', Y} when is_list(Y) -> - is_proplist(Y); - _ -> - false - end; -check_term_predef(string, X) -> - case X of - {'#S', Y} when is_list(Y) -> - is_string(Y); - _ -> - false - end; -check_term_predef(term, _X) -> - true; check_term_predef(tuple, X) -> is_tuple(X); -check_term_predef(none, _X) -> - true; +check_term_predef({any,Attrs}, X) -> + check_term_attrlist(any,Attrs,X); check_term_predef({atom,Attrs}, X) -> is_atom(X) andalso check_term_attrlist(atom,Attrs,X); -check_term_predef({boolean,Attrs}, X) -> - is_boolean(X) andalso check_term_attrlist(boolean,Attrs,X); check_term_predef({binary,Attrs}, X) -> is_binary(X) andalso check_term_attrlist(binary,Attrs,X); check_term_predef({list,Attrs}, X) -> is_list(X) andalso check_term_attrlist(list,Attrs,X); -check_term_predef({proplist,Attrs}, X) -> - case X of - {'#P', Y} when is_list(Y) -> - is_proplist(Y) andalso check_term_attrlist(proplist,Attrs,X); - _ -> - false - end; -check_term_predef({string,Attrs}, X) -> - case X of - {'#S', Y} when is_list(Y) -> - is_string(Y) andalso check_term_attrlist(string,Attrs,X); - _ -> - false - end; -check_term_predef({term,Attrs}, X) -> - check_term_attrlist(term,Attrs,X); check_term_predef({tuple,Attrs}, X) -> is_tuple(X) andalso check_term_attrlist(tuple,Attrs,X). - %% check_term_attrlist check_term_attrlist(Type, Attrs, Val) -> [] == [ {Type,Attr,Val} || Attr <- Attrs, not check_term_attr(Type,Attr,Val) ]. @@ -412,21 +361,6 @@ check_term_attr(Type,nonundefined,Val) -> check_term_attr(_,_,_) -> false. - -%% is_string -is_string([H|T]) when is_integer(H), H < 256, H > -1 -> - is_string(T); -is_string([]) -> true; -is_string(_) -> false. - - -%% is_proplist -is_proplist([P|T]) when tuple_size(P) =:= 2 -> - is_proplist(T); -is_proplist([]) -> true; -is_proplist(_) -> false. - - %% is_ascii is_ascii(A) when is_atom(A) -> is_ascii(atom_to_list(A)); diff --git a/src/qc_ubf_types.erl b/src/qc_ubf_types.erl index 5053d6a..3043afd 100644 --- a/src/qc_ubf_types.erl +++ b/src/qc_ubf_types.erl @@ -109,9 +109,6 @@ type1(_Gen,{range,Lo,Hi}) -> %% atom type1(_Gen,{atom,Value}) when is_atom(Value) -> Value; -%% boolean -type1(_Gen,{boolean,Value}) when is_boolean(Value) -> - Value; %% binary type1(_Gen,{binary,Value}) when is_binary(Value) -> Value; @@ -125,10 +122,13 @@ type1(_Gen,{integer,Value}) when is_integer(Value) -> type1(_Gen,{string,Value}) when is_list(Value) -> Value; %% predef +type1(_Gen,{predef,any}) -> + qc_gen:qc_term(); +type1(_Gen,{predef,none}) -> + %% not supported + exit(fatal); type1(_Gen,{predef,atom}) -> qc_gen:qc_atom(); -type1(_Gen,{predef,boolean}) -> - bool(); type1(_Gen,{predef,integer}) -> oneof([int(),largeint()]); type1(_Gen,{predef,float}) -> @@ -137,30 +137,17 @@ type1(_Gen,{predef,binary}) -> qc_gen:qc_binary(); type1(_Gen,{predef,list}) -> qc_gen:qc_list(); -type1(_Gen,{predef,proplist}) -> - ?P(qc_gen:qc_proplist()); -type1(_Gen,{predef,string}) -> - ?S(qc_gen:qc_string()); type1(_Gen,{predef,tuple}) -> qc_gen:qc_tuple(); -type1(_Gen,{predef,term}) -> - qc_gen:qc_term(); -type1(_Gen,{predef,none}) -> - %% not supported - exit(fatal); %% predef with attributes +type1(_Gen,{predef,{any,Attrs}}) -> + qc_gen:qc_term(Attrs); type1(_Gen,{predef,{atom,Attrs}}) -> qc_gen:qc_atom(Attrs); type1(_Gen,{predef,{binary,Attrs}}) -> qc_gen:qc_binary(Attrs); type1(_Gen,{predef,{list,Attrs}}) -> qc_gen:qc_list(Attrs); -type1(_Gen,{predef,{proplist,Attrs}}) -> - ?P(qc_gen:qc_proplist(Attrs)); -type1(_Gen,{predef,{string,Attrs}}) -> - ?S(qc_gen:qc_string(Attrs)); -type1(_Gen,{predef,{term,Attrs}}) -> - qc_gen:qc_term(Attrs); type1(_Gen,{predef,{tuple,Attrs}}) -> qc_gen:qc_tuple(Attrs); %% abnf diff --git a/src/ubf.app.src b/src/ubf.app.src index d4fc332..356776d 100644 --- a/src/ubf.app.src +++ b/src/ubf.app.src @@ -32,6 +32,7 @@ {modules, [contract_parser , contract_lex , contract_yecc + , ubf_types_builtin , ubf_client , ubf_server , ubf_plugin_handler diff --git a/src/ubf_client.erl b/src/ubf_client.erl index f92e19d..9c3d051 100644 --- a/src/ubf_client.erl +++ b/src/ubf_client.erl @@ -234,7 +234,7 @@ ubf_client(Parent, Plugins, Server, Options, Timeout) when is_list(Plugins) andalso length(Plugins) > 0 andalso is_pid(Server) andalso is_list(Options) -> process_flag(trap_exit, true), Driver = ubf_server:start_term_listener(Server, Plugins, Options), - ServerHello = proplists:get_value(serverhello, Options, defined), + ServerHello = proplists:get_value(serverhello, Options, true), SimpleRPC = proplists:get_value(simplerpc, Options, false), if ServerHello =/= undefined -> %% wait for a startup message diff --git a/src/ubf_plugin_meta.con b/src/ubf_plugin_meta.con index f0dac4a..1642ff6 100644 --- a/src/ubf_plugin_meta.con +++ b/src/ubf_plugin_meta.con @@ -25,7 +25,7 @@ +NAME("meta_server"). -+VSN("ubf1.0"). ++VSN("ubf2.0"). +TYPES @@ -33,11 +33,11 @@ info() :: info; description() :: description; services() :: services; contract() :: contract; -serviceList() :: [string()] "Names of the offered services"; +serviceList() :: [ubfstring()] "Names of the offered services"; help() :: help; -restartService() :: {restartService, string(), term()}; -startSession() :: {startSession, string(), term()}; +restartService() :: {restartService, ubfstring(), term()}; +startSession() :: {startSession, ubfstring(), term()}; ok() :: {ok, term()}; error() :: {error, term()}; ok_or_error() :: ok() | error(). diff --git a/src/ubf_server.erl b/src/ubf_server.erl index 0dde7a8..8ac44f5 100644 --- a/src/ubf_server.erl +++ b/src/ubf_server.erl @@ -104,7 +104,7 @@ start(Name, Plugins, Port) -> %% - +{proto, {ubf | ebf | atom()}}+ Enable the UBF, EBF, or %% an alternative protocol wire format. %% Default: ubf. -%% - +{proto, {ubf | ebf | atom(), proplist()}}+ Enable the UBF, +%% - +{proto, {ubf | ebf | atom(), [atom() | tuple()]}}+ Enable the UBF, %% EBF, or an alternative protocol wire format with options. %% Default: +{ubf, []}+. %% @@ -125,7 +125,7 @@ start(Name, Plugins, Port) -> %% client first connects to the server. If not set, client may %% select the service using the startSession() API. There is %% no default setting. -%% - +{serverhello, string() | undefined}+ Meta contract greeting +%% - +{serverhello, ubfstring() | undefined}+ Meta contract greeting %% string, sent when a client first connects to the server. If %% undefined, server hello is not sent to the client. %% Default: "meta_server". diff --git a/src/ubf_types_builtin.con b/src/ubf_types_builtin.con new file mode 100644 index 0000000..8b9f63a --- /dev/null +++ b/src/ubf_types_builtin.con @@ -0,0 +1,124 @@ +%%% -*- mode: erlang -*- +%%% + ++NAME("ubf_types_builtin"). + ++VSN("ubf2.0"). + + +%% +%% Excerpt from http://www.erlang.org/eeps/eep-0008.html +%% +%% For convenience, the following types are also built-in. They can be +%% thought as predefined aliases for the type unions also shown in the +%% table. (Some type unions below slightly abuse the syntax of types.) +%% +%% ========================== ===================================== +%% Built-in type Stands for +%% ========================== ===================================== +%% ``term()`` ``any()`` +%% ``boolean()`` ``'false' | 'true'`` +%% ``byte()`` ``0..255`` +%% ``char()`` ``0..16#10ffff`` +%% ``non_neg_integer()`` ``0..`` +%% ``pos_integer()`` ``1..`` +%% ``neg_integer()`` ``..-1`` +%% ``number()`` ``integer() | float()`` +%% ``list()`` ``[any()]`` +%% ``maybe_improper_list()`` ``maybe_improper_list(any(), any())`` +%% ``maybe_improper_list(T)`` ``maybe_improper_list(T, any())`` +%% ``string()`` ``[char()]`` +%% ``nonempty_string()`` ``[char(),...]`` +%% ``iolist()`` ``maybe_improper_list(`` +%% ``char() | binary() |`` +%% ``iolist(), binary() | [])`` +%% ``module()`` ``atom()`` +%% ``mfa()`` ``{atom(),atom(),byte()}`` +%% ``node()`` ``atom()`` +%% ``timeout()`` ``'infinity' | non_neg_integer()`` +%% ``no_return()`` ``none()`` +%% ========================== ===================================== +%% +%% Users are not allowed to define types with the same names as the +%% predefined or built-in ones. This is checked by the compiler and +%% its violation results in a compilation error. (For bootstrapping +%% purposes, it can also result to just a warning if this involves a +%% built-in type which has just been introduced.) +%% +%% *NOTE*: The following built-in list types also exist, but they are +%% expected to be rarely used. Hence, they have long names: +%% +%% :: +%% +%% nonempty_maybe_improper_list(Type) :: nonempty_maybe_improper_list(Type, any()) +%% nonempty_maybe_improper_list() :: nonempty_maybe_improper_list(any()) +%% +%% where the following two types +%% +%% :: +%% +%% nonempty_improper_list(Type1, Type2) +%% nonempty_maybe_improper_list(Type1, Type2) +%% +%% define the set of Erlang terms one would expect. +%% + + +%% +%% Supported eep8 predefined types: +%% +%% via ubf predefined types +%% - any() +%% - none() +%% - list() +%% +%% via ubf contract +%% - nil() +%% - term() +%% - byte() +%% - char() +%% - non_neg_integer() +%% - pos_integer() +%% - neg_integer() +%% - number() +%% - string() +%% - nonempty_string() +%% - module() +%% - mfa() +%% - node() +%% - timeout() +%% - no_return() +%% +%% not implemented +%% - iolist() +%% - maybe_improper_list() +%% - maybe_improper_list(T) +%% - nonempty_maybe_improper_list() +%% - nonempty_maybe_improper_list(T) +%% + + +%%%%%% ++TYPES + +%% Erlang built-in types +nil() :: []; +term() :: any(); +boolean() :: 'false' | 'true'; +byte() :: 0..255; +char() :: 0..16#10ffff; +non_neg_integer() :: 0..; +pos_integer() :: 1..; +neg_integer() :: ..-1; +number() :: integer() | float(); +string() :: [char()]; +nonempty_string() :: [char()]+; +module() :: atom(); +mfa() :: {atom(), atom(), byte()}; +node() :: atom(); +timeout() :: 'infinity' | non_neg_integer(); +no_return() :: none(); + +%% UBF built-in types +ubfproplist() :: {'#P', [{term(), term()}]}; +ubfstring() :: {'#S', [byte()]}. diff --git a/src/ubf_types_builtin.erl b/src/ubf_types_builtin.erl new file mode 100644 index 0000000..0fcb880 --- /dev/null +++ b/src/ubf_types_builtin.erl @@ -0,0 +1,12 @@ +%%% + +%%% @doc UBF TYPES builtin types +%%% +%%% @end +%%% + +-module(ubf_types_builtin). + +%% NOTE the following three lines +-compile({parse_transform,contract_parser}). +-add_contract("src/ubf_types_builtin"). diff --git a/src/ubf_utils.erl b/src/ubf_utils.erl index d7d3fea..c131382 100644 --- a/src/ubf_utils.erl +++ b/src/ubf_utils.erl @@ -77,12 +77,15 @@ ubf_contract2(C) -> , "% false\n%\t\tfalse" , "% undefined\n%\t\tundefined" , "%" + , "% any()\n%\t\tany" + , "% any()?\n%\t\tany | undefined" + , "%" + , "% none()\n%\t\t /* no result is returned */" + , "% none()?\n%\t\t /* no result is returned */ | undefined" + , "%" , "% atom()\n%\t\tatom" , "% atom()?\n%\t\tatom | undefined" , "%" - , "% boolean()\n%\t\tboolean" - , "% boolean()?\n%\t\tboolean | undefined" - , "%" , "% binary()\n%\t\tbinary" , "% binary()?\n%\t\tbinary | undefined" , "%" @@ -95,25 +98,16 @@ ubf_contract2(C) -> , "% list()\n%\t\tlist" , "% list()?\n%\t\tlist | undefined" , "%" - , "% proplist()\n%\t\t{'#P',proplist}" - , "% proplist()?\n%\t\t{'#P',proplist} | undefined" - , "%" - , "% string()\n%\t\t{'#S',string}" - , "% string()?\n%\t\t{'#S',string} | undefined" - , "%" - , "% term()\n%\t\tterm" - , "% term()?\n%\t\tterm | undefined" - , "%" , "% tuple()\n%\t\ttuple" , "% tuple()?\n%\t\ttuple | undefined" , "%" - , "% none()\n%\t\t /* no result is returned */" - , "% none()?\n%\t\t /* no result is returned */ | undefined" - , "%" , "%% --------------------" , "%% type attributes" , "%%" , "%" + , "% any(AnyAttrs)\n%\t\tany" + , "% any(AnyAttrs)?\n%\t\tany | undefined" + , "%" , "% atom(AtomAttrs)\n%\t\tatom" , "% atom(AtomAttrs)?\n%\t\tatom | undefined" , "%" @@ -123,17 +117,13 @@ ubf_contract2(C) -> , "% list(ListAttrs)\n%\t\tlist" , "% list(ListAttrs)?\n%\t\tlist | undefined" , "%" - , "% proplist(PropListAttrs)\n%\t\t{'#P',proplist}" - , "% proplist(PropListAttrs)?\n%\t\t{'#P',proplist} | undefined" - , "%" - , "% string(StringAttrs)\n%\t\t{'#S',string}" - , "% string(StringAttrs)?\n%\t\t{'#S',string} | undefined" - , "%" , "% tuple(TupleAttrs)\n%\t\ttuple" , "% tuple(TupleAttrs)?\n%\t\ttuple | undefined" , "%" - , "% term(TermAttrs)\n%\t\tterm" - , "% term(TermAttrs)?\n%\t\tterm | undefined" + , "%" + , "% AnyAttrs" + , "% \t nonempty" + , "% \t nonundefined" , "%" , "% AtomAttrs" , "% \t ascii | asciiprintable" @@ -147,17 +137,6 @@ ubf_contract2(C) -> , "% ListAttrs" , "% \t nonempty" , "%" - , "% PropListAttrs" - , "% \t nonempty" - , "%" - , "% StringAttrs" - , "% \t ascii | asciiprintable" - , "% \t nonempty" - , "%" - , "% TermAttrs" - , "% \t nonempty" - , "% \t nonundefined" - , "%" , "% TupleAttrs" , "% \t nonempty" , "%" @@ -366,9 +345,6 @@ typeref(_Style,{range,Lo,Hi},_C) -> %% atom typeref(_Style,{atom,Value},_C) -> io_lib:format("~p", [Value]); -%% boolean -typeref(_Style,{boolean,Value},_C) -> - io_lib:format("~p", [Value]); %% binary typeref(_Style,{binary,Value},_C) -> io_lib:format("~p", [Value]); @@ -382,10 +358,12 @@ typeref(_Style,{integer,Value},_C) -> typeref(_Style,{string,Value},_C) -> io_lib:format("~p", [Value]); %% predef +typeref(_Style,{predef,any},_C) -> + "any()"; +typeref(_Style,{predef,none},_C) -> + "none()"; typeref(_Style,{predef,atom},_C) -> "atom()"; -typeref(_Style,{predef,boolean},_C) -> - "boolean()"; typeref(_Style,{predef,binary},_C) -> "binary()"; typeref(_Style,{predef,float},_C) -> @@ -394,31 +372,17 @@ typeref(_Style,{predef,integer},_C) -> "integer()"; typeref(_Style,{predef,list},_C) -> "list()"; -typeref(_Style,{predef,proplist},_C) -> - "proplist()"; -typeref(_Style,{predef,string},_C) -> - "string()"; -typeref(_Style,{predef,term},_C) -> - "term()"; typeref(_Style,{predef,tuple},_C) -> "tuple()"; -typeref(_Style,{predef,none},_C) -> - "none()"; %% predef with attributes +typeref(_Style,{predef,{any,Attrs}},_C) -> + io_lib:format("any(~s)", [join([ atom_to_list(Attr) || Attr <- Attrs ], ",")]); typeref(_Style,{predef,{atom,Attrs}},_C) -> io_lib:format("atom(~s)", [join([ atom_to_list(Attr) || Attr <- Attrs ], ",")]); -typeref(_Style,{predef,{boolean,Attrs}},_C) -> - io_lib:format("boolean(~s)", [join([ atom_to_list(Attr) || Attr <- Attrs ], ",")]); typeref(_Style,{predef,{binary,Attrs}},_C) -> io_lib:format("binary(~s)", [join([ atom_to_list(Attr) || Attr <- Attrs ], ",")]); typeref(_Style,{predef,{list,Attrs}},_C) -> io_lib:format("list(~s)", [join([ atom_to_list(Attr) || Attr <- Attrs ], ",")]); -typeref(_Style,{predef,{proplist,Attrs}},_C) -> - io_lib:format("proplist(~s)", [join([ atom_to_list(Attr) || Attr <- Attrs ], ",")]); -typeref(_Style,{predef,{string,Attrs}},_C) -> - io_lib:format("string(~s)", [join([ atom_to_list(Attr) || Attr <- Attrs ], ",")]); -typeref(_Style,{predef,{term,Attrs}},_C) -> - io_lib:format("term(~s)", [join([ atom_to_list(Attr) || Attr <- Attrs ], ",")]); typeref(_Style,{predef,{tuple,Attrs}},_C) -> io_lib:format("tuple(~s)", [join([ atom_to_list(Attr) || Attr <- Attrs ], ",")]); %% otherwise diff --git a/test/eunit/stateful_plugin.con b/test/eunit/stateful_plugin.con index fbaf6c4..e679423 100644 --- a/test/eunit/stateful_plugin.con +++ b/test/eunit/stateful_plugin.con @@ -25,7 +25,7 @@ +NAME("test"). -+VSN("ubf1.0"). ++VSN("ubf2.0"). %%%%% %%% states diff --git a/test/eunit/stateless_plugin.con b/test/eunit/stateless_plugin.con index b80bbdf..ff92adf 100644 --- a/test/eunit/stateless_plugin.con +++ b/test/eunit/stateless_plugin.con @@ -25,7 +25,7 @@ +NAME("test"). -+VSN("ubf1.0"). ++VSN("ubf2.0"). %%%%% diff --git a/test/eunit/types_plugin.con b/test/eunit/types_plugin.con index f25270b..1470c6b 100644 --- a/test/eunit/types_plugin.con +++ b/test/eunit/types_plugin.con @@ -25,7 +25,7 @@ +NAME("types"). -+VSN("ubf1.0"). ++VSN("ubf2.0"). %%%%%% +TYPES @@ -33,11 +33,9 @@ %%%%% %%% well-known primitives -bool() :: true | false; expires() :: {integer(), integer(), integer()}; %% erlang-style timestamp opaque() :: binary(); time_t() :: integer(); -timeout() :: infinity | integer(); %% milliseconds timeout_or_expires() :: timeout() | expires(); ts() :: integer(); utf8() :: binary(); @@ -84,10 +82,10 @@ ubf_keepalive_res() :: ok; %%%%% %%% meta methods ubf_info_req() :: info; -ubf_info_res() :: string(); +ubf_info_res() :: ubfstring(); ubf_description_req() :: description; -ubf_description_res() :: string(); +ubf_description_res() :: ubfstring(); ubf_contract_req() :: contract; ubf_contract_res() :: term(). diff --git a/test/unit/file_plugin.con b/test/unit/file_plugin.con index bb04455..da83959 100644 --- a/test/unit/file_plugin.con +++ b/test/unit/file_plugin.con @@ -25,7 +25,7 @@ +NAME("file_server"). -+VSN("ubf1.0"). ++VSN("ubf2.0"). +TYPES @@ -33,7 +33,7 @@ info() :: info; description() :: description; contract() :: contract; -file() :: string(); +file() :: ubfstring(); ls() :: ls; files() :: {files, [file()]}; getFile() :: {get, file()}; diff --git a/test/unit/irc_plugin.con b/test/unit/irc_plugin.con index 796c55c..3753b62 100644 --- a/test/unit/irc_plugin.con +++ b/test/unit/irc_plugin.con @@ -25,7 +25,7 @@ +NAME("irc"). -+VSN("ubf1.0"). ++VSN("ubf2.0"). +TYPES info() :: info; @@ -34,10 +34,10 @@ contract() :: contract; ok() :: ok; bool() :: true | false; -nick() :: string(); +nick() :: ubfstring(); oldnick() :: nick(); newnick() :: nick(); -group() :: string(); +group() :: ubfstring(); groups() :: [group()]; logon() :: logon; diff --git a/test/unit/test_plugin.con b/test/unit/test_plugin.con index 0f6a665..5a47753 100644 --- a/test/unit/test_plugin.con +++ b/test/unit/test_plugin.con @@ -25,7 +25,7 @@ +NAME("test"). -+VSN("ubf1.0"). ++VSN("ubf2.0"). +TYPES @@ -33,27 +33,25 @@ info() :: info; description() :: description; services() :: services; contract() :: contract; -serviceList() :: [string()]; +serviceList() :: [ubfstring()]; dummy() :: {dummy, dummyrecord()}; dummyrecord() :: #dummyrecord{foo::integer(), bar::binary()}; dummy1a() :: atom(ascii,nonempty,nonundefined); dummy1b() :: atom(asciiprintable,nonempty,nonundefined); -dummy2a() :: string(ascii,nonempty); -dummy2b() :: string(asciiprintable,nonempty); dummy3a() :: binary(ascii,nonempty); dummy3b() :: binary(asciiprintable,nonempty); -dummy4() :: term(nonempty,nonundefined); +dummy4() :: any(nonempty,nonundefined); dummy5() :: #dummy5{hoge1::1, hoge2::two, hoge3::3.0, hoge4::<<"4">>}; -password() :: string(); -file() :: string(); +password() :: ubfstring(); +file() :: ubfstring(); noSuchFile() :: {error, noSuchFile}; doubleInt() :: [integer()]; -upCase() :: string(); +upCase() :: ubfstring(); logon() :: {logon, password()}; ls() :: ls; -files() :: {files, [string()]} "request a list of file"; +files() :: {files, [ubfstring()]} "request a list of file"; callback() :: {callback, none()}; getFile() :: {get, file()}; okFile() :: {ok, binary()}; @@ -63,7 +61,7 @@ ack() :: ack; error() :: error; ok() :: ok; intList() :: [integer()]; -propList() :: proplist(); +propList() :: ubfproplist(); testAmbiguities() :: testAmbiguities; foo() :: #foo{attribute1::term()}; callbackOnItsWay() :: callbackOnItsWay. @@ -83,7 +81,7 @@ callbackOnItsWay() :: callbackOnItsWay. EVENT <= callback(). +STATE funny - string() => upCase() & funny; + ubfstring() => upCase() & funny; intList() => doubleInt() & funny; propList() => propList() & funny; stop() => ack() & start. @@ -92,14 +90,12 @@ callbackOnItsWay() :: callbackOnItsWay. dummy() => dummy(); dummy1a() => dummy1a(); dummy1b() => dummy1b(); - dummy2a() => dummy2a(); - dummy2b() => dummy2b(); dummy3a() => dummy3a(); dummy3b() => dummy3b(); dummy4() => dummy4(); dummy5() => dummy5(); foo() => term(); - info() => string(); - description() => string(); + info() => ubfstring(); + description() => ubfstring(); services() => serviceList(); contract() => term().