原文地址: http://www-verimag.imag.fr/TOOLS/DCS/bip/doc/latest/html/language.html BIP2(Behaviour,Interaction、Priority version2)是一个用于对复杂系统进行建模和编程的面向构件的语言,基本概念如下: behaviour:用于描述一系列构件 interaction:用于定义构件之间可能存在的同步和通讯 priority:用于解决interacion之间的冲突以及定义interaction排列的规则 compound component(compounds):由一系列component、connector、priority组成 atomic component(atoms):原子构件,其行为用自动机或Petri网来表示 port:用于以构件之间以同步方式进行通讯 variable:用于存储通过优先级和迁移保护表达式来解决冲突和不确定问题的信息 model:一个复合构件,用于描述想要模拟、分析、验证或执行的系统
Annotations 注释可以用于定义那些被工具而不是编译器识别的内容。编译器会检查注释语句的语法,但是会忽略里面的内容。接受注释的BIP2语句会使用以下内容来标记
- accepts annotations
Packages package是一个编译单元,它包含在一个文件中。可以通过 use来引入其他包,可以包含:
- 常量数据
- 外部数据类型
- 原子类型
- 连接器类型
- 复合类型
常量在类型定义或者其他常量数据的初始化中用到。 常量数据仅在包含其定义的包中有效。
重要:BIP语言允许声明一个类型用于简单类型(float、int、double、bool)的检查, 但不允许定义一个类型(类、结构体等)。由后端语言负责类型的解释。(后端语言C++会将这些类型直接转化成C++中对应的类型) 重要:当需要使用其他包中声明的类型时, 需要以声明该类型的包名作为前缀来命名。
Variables variable由其类型和变量名组成。例如: int x 声明了一个类型为int,变量名为x的变量。
变量类型可以是 局部native 或者 外部external 的。局部类型作为BIP语言的一部分可以被BIP语言编译器识别。目前支持的局部类型有int、float、double和char。不同类型的变量所分配的内存空间由所使用的后端语言决定。外部类型必须用 extern 关键字来声明。变量可以在连接器和原子构件中使用。
比较操作符:==、!=、<、>、<=、>= 算术操作符:/、%、+、-、* 布尔操作符:&&、||、&、|、^、~、! 赋值操作符:=
重要:在BIP语言中, 数据类型和操作符并不像在其它语言中那样被完整的定义。所有运算的具体行为(如整型和浮点类型的上限和下限)都没有被定义。目前,这些行为都由后端语言去实现(通过将BIP语言中的类型和运算符转换成后端语言中的类型和运算符)。
Actions actions定义了所有的计算和数据转换操作。在不可变的上下文中,actions必须进行对BIP语言和外部变量合法的运算。引用外部函数可能会出现BIP编译器无法检查的非法运算,因此使用的时候应该人工避免这些非法运算。在可变的上下文中,计算和数据转换操作都是允许的。
当引用外部代码时,编译器无法保证不可变的上下文中没有非法运算。另外,在一些混合的上下文有一部分数据是可变的,一部分数据是不可变的。因此,编译器会限制所有的actions来保证它们都是不可变的。
actions中的计算和数据转换操作都是采用类C语法的语句和表达式来描述的,它们将数值和函数结果用算术、逻辑和位运算符连接起来。通过括号来使表达式成为一个整体并使它们按照指定的顺序进行运算。一个action中的多个语句会放在大括号中,同时每个语句以;分隔。
在不可变的上下文中,如果一个action中含有被括号包围的单一表达式,就必须计算出true或者false。在C++作为后端语言时,任何非0值都会被认为是true。其他后端语言可能会对计算出来的值有更严格的要求。
重要:actions在不同的构件中,引用变量的方式也不同。例如,在原子构件中,可以直接使用所声明的变量名来引用变量。而在连接器的端口中引用变量必须采用点符号(如端口名.变量名)
在actions中只有一个控制流操作:if/then/else,其中else是可选的
Petri net Petri nets实现了原子构件的行为,由places和transitions组成。places用于存储原子构件当前位于的控制位置,通过一个会对指定的位置返回true的布尔函数来标识位置。places在原子构件中用places后面跟随一系列位置的名字来声明,如:
places START, SYNC, END
transitions改变原子构件当前的状态并调用相应的actions来改变原子构件中变量的值。一个transition包括:
- 一系列triggering places(当前状态下发生迁移所必须标记的,用from来声明)
- 一系列target places(在迁移之后被标记的,用to来声明)
- 一个布尔条件guard(当前状态下发生迁移所需局部变量的值,用provided来声明),如果没有,则对该迁移没有限制
- 一段可选的代码,在迁移之后执行(用do来声明)
当以下条件满足时,原子构件发生迁移:
- 当前状态下所有的triggering places都被标记
- 相应的guard值为true或者不存在guard
有三种类型的迁移如下:
- initial迁移负责初始化标记的位置和原子构件的变量,是模型初始化时必须进行的迁移。除此之外,初始迁移不能被其他构件访问,也不能与其他迁移同步。
- internal迁移不能被其他构件访问且优先级要高于其他可访问的迁移。
- on迁移以internal port作为标签,可以被其他构件访问,也可以被其他构件的迁移用connectors进行同步。
重要:任何时候都只能同时进行一个internal迁移,因为原子构件的internal迁移都是唯一的。同样的,两个用同样internal port作为标签的迁移不能同时进行。