feat(mtc): .mt 脚本编译器落地 + pybot 扬声器静音语义
mtc 新模块:命令式动作脚本(Python DSL)→ .mt 矩阵编译器,非阻塞时间轴 IR(重叠截断/rest 静止值)+ 10ms 栅格化,产物可由 pybot/bot4cj 直接执行;34 测试全绿(含 pybot parser e2e)。 pybot speaker.py:frequency<=0 改为静音节拍(仅 sleep 保时序,不再钳到 min_f 低鸣),对齐仓颉版 sleep 占位语义;mtc Beep 通道 rest=0,段前/段间/段后回落静音,两侧语义闭环。 修复 test_actpred_compatibility 过时断言(99c1bc1 首行分解为重复微步 19→20 帧时漏改,14→15)。 文档三处同步:根 README 回填 memdb/pybot/actpred 并新增 mtc(模块表+端口一览+章节),MODULES/ARCHITECTURE 同步 mtc,新建 mtc/README.md。
This commit is contained in:
1 parent
205a60f039
commit
01126a5786
18 files changed
+1125
-7
No files matched your search
@@ -0,0 +1,64 @@
|
||||
"""端到端:mtc 编译产物 → pybot MatrixParser 解析断言
|
||||
|
||||
验证闭环:编译产物必须被 pybot 零修改解析(列数一致、Q05 表头
|
||||
'设备.参数' 校验、栅格行数与数值逐一比对)。
|
||||
"""
|
||||
|
||||
from mtc.dsl import compile_script
|
||||
from tests.conftest import load_pybot_parser
|
||||
from tests.test_emit import EXAMPLE
|
||||
|
||||
|
||||
def _parse(mt_text):
|
||||
parser_mod = load_pybot_parser()
|
||||
parser = parser_mod.MatrixParser(mt_text)
|
||||
objects = []
|
||||
while True:
|
||||
obj = parser.parse()
|
||||
if obj is None:
|
||||
break
|
||||
objects.append(obj)
|
||||
return objects
|
||||
|
||||
|
||||
def test_compiled_mt_parses_with_pybot():
|
||||
objs = _parse(compile_script(EXAMPLE)[0])
|
||||
names = [o.name for o in objs]
|
||||
assert names == ["Servo", "Speaker", "Action"]
|
||||
action = objs[names.index("Action")]
|
||||
assert action.size == 11 # 表头 + 10 栅格行
|
||||
assert action.col == 4 # s1/s2 + spk.frequency + spk.delay
|
||||
for row in action.values: # 列数一致(DoesNotSync 不触发)
|
||||
assert len(row) == action.col
|
||||
|
||||
|
||||
def test_compiled_action_grid_values():
|
||||
objs = _parse(compile_script(EXAMPLE)[0])
|
||||
action = [o for o in objs if o.name == "Action"][0]
|
||||
assert action.values[0] == ["s1.angle", "s2.angle",
|
||||
"spk.frequency", "spk.delay"]
|
||||
grid = action.values[1:]
|
||||
assert [r[0] for r in grid] == [str(i) for i in range(1, 11)]
|
||||
assert [r[1] for r in grid] == ["0"] * 5 + ["4", "8", "12", "16", "20"]
|
||||
assert {r[2] for r in grid} == {"0"} # 无 Beep:frequency 恒 0
|
||||
assert {r[3] for r in grid} == {"10"}
|
||||
|
||||
|
||||
def test_compiled_mt_roundtrips_through_pybot():
|
||||
"""编译产物经 pybot 解析→序列化→再解析等价(roundtrip 自检)"""
|
||||
import io
|
||||
parser_mod = load_pybot_parser()
|
||||
objs = _parse(compile_script(EXAMPLE)[0])
|
||||
out = io.StringIO()
|
||||
parser_mod.MatrixSaver(out).save(objs)
|
||||
objs2 = _parse(out.getvalue())
|
||||
assert [(a.name, a.values) for a in objs] == \
|
||||
[(b.name, b.values) for b in objs2]
|
||||
|
||||
|
||||
def test_q05_header_contract_holds():
|
||||
"""@Action 全部列名恰含一个 '.'(pybot robot._validate_action 契约)"""
|
||||
objs = _parse(compile_script(EXAMPLE)[0])
|
||||
action = [o for o in objs if o.name == "Action"][0]
|
||||
for col in action.values[0]:
|
||||
assert col.count(".") == 1
|
||||
Reference in new issue
Block a user