Page 138 - 《软件学报》2025年第8期
P. 138
于涛 等: 基于下推自动机的同步数据流语言可信编译 3561
名流, 而非将 A 的流改变为 ck.
表 4 为 3 个时钟算子的目标码模式. 其中 when 运算符的目标码为第 1 个表达式的值, 因为 when 运算符在表
达式中不改变目标码, 仅告知编译器流的时钟即可. current 运算符在时钟为 false 时返回上一个有效的值, 因此依
赖于先前周期的信息, 所以目标码和时态算子一样, 使用辅助函数和上下文结构体的方式实现. merge 运算符将多
个互补的流融合为一个流, 因此每个周期都有一个有效值, 不依赖于先前周期.
表 4 时钟算子目标码模式
产生式左部 产生式右部 目标码模式
<Expression> when <Expression> <Expression>
Expression current <Expression> current_function(<Expression>, <Expression>, ctx)
merge <Lv6Id> <Mergecaselist> switch(<Lv6Id>) {< Mergecaselist>}
以 merge 运算符为例, <Mergecaselist> 在 merge 产生式的转换中不做处理, 交由<Mergecaselist> 产生式转换,
其产生式和目标码模式如表 5 所示, 本质上是填补了 C 语言 switch 语句中 case 的部分.
表 5 merge 运算符目标码模式
产生式左部 产生式右部 目标码模式
<MergeCase> <Mergecaselist> <MergeCase> <Mergecaselist>
Mergecaselist <MergeCase> <MergeCase>
empty -
(Lv6Id → <Expression>) case Lv6Id: temp = <Expression>; break;
MergeCase (true → <Expression>) case true: temp = <Expression>; break;
(false → <Expression>) case false: temp = <Expression>; break;
3.3 C 代码生成
代码生成的过程大致可分为 3 个步骤: (1) 通过下推自动机识别算法对程序进行识别的同时生成 Lustre 程序
的目标码; (2) 生成 Lustre 程序所有节点和辅助函数、结构体的目标码; (3) 生成 C 目标代码主循环.
在目标码转换模式和下推自动机的基础上, 将目标码转换模式拆解为具体的转换动作, 即每个下推自动机识
别过程中的状态转移动作需要执行的转换动作. 随后将转换动作嵌入到下推自动机识别算法当中, 在识别的同时
就完成了 Lustre 源程序的转换.
表 6 以伪代码形式展示了 Lustre 程序与 C 程序的对应关系, Lustre 程序主要由 node 组成, 每一个 node 对应
于 C 程序中的一个函数. 由于 Lustre 的输入参数与输出参数可能不止一个值, 因此在 C 程序中使用输入和输出结
构体来描述各个参数的类型. <expr> 表达式由算术和逻辑表达式, 条件表达式, 时态表达式, 节点调用组成; 分别
对应于 C 语言中的算术和逻辑表达式, 条件表达式, 条件表达式, 函数调用.
表 6 Lustre 程序及对应的 C 程序
Lustre程序 Lustre程序对应的C程序
typedef struct{
paraType para1;
paraType para2;
node function(para1,
}function_in;
para2:paraType)
typedef struct{
returns(retPara1,
retType retPara1;
retPara2:retType)
retType retPara2;
let
}function_out;
<expr1>
void function(function_in *in, function_out
<expr2>
*out){
<expr3>
<expr1>
tel
<expr2>
<expr3>
}

