同步KDL工程源码到云仓库
This commit is contained in:
153
kdl-wasm/web/tests/grl/operationCompile.test.ts
Normal file
153
kdl-wasm/web/tests/grl/operationCompile.test.ts
Normal file
@@ -0,0 +1,153 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import type {
|
||||
GrlOperationDeclaration,
|
||||
GrlPathDeclaration,
|
||||
GrlProcedureDeclaration
|
||||
} from "../../src/grl/ast/index.js";
|
||||
import { parseGrl } from "../../src/grl/parser/index.js";
|
||||
import {
|
||||
compileOperation,
|
||||
expandRunOperation,
|
||||
parseProcedureRunOperationStatements
|
||||
} from "../../src/grl/semantic/index.js";
|
||||
|
||||
const PROGRAM = `language grl 0.1
|
||||
module Main
|
||||
const speed v = joint(50 %)
|
||||
const zone zf = fine
|
||||
target home = joint_target { joints: [0 deg] }
|
||||
path weld_path {
|
||||
defaults { speed: v, zone: zf }
|
||||
point p0 movej home
|
||||
}
|
||||
operation weld_op_01 {
|
||||
kind: arc_welding
|
||||
path: weld_path
|
||||
process {
|
||||
weld_id: "WELD_1"
|
||||
voltage: 24.0
|
||||
current: 180.0
|
||||
weave: none
|
||||
}
|
||||
start_action:
|
||||
io.do[20] = true
|
||||
end_action:
|
||||
io.do[20] = false
|
||||
}
|
||||
proc main()
|
||||
run_operation weld_op_01
|
||||
end
|
||||
end
|
||||
`;
|
||||
|
||||
function declarations() {
|
||||
return parseGrl(PROGRAM).module.declarations;
|
||||
}
|
||||
|
||||
function pathsByName(paths: GrlPathDeclaration[]) {
|
||||
return new Map(paths.map((path) => [path.name, path]));
|
||||
}
|
||||
|
||||
describe("GRL operation compilation", () => {
|
||||
it("parses operation kind, path, process, and action blocks", () => {
|
||||
const operation = declarations().find(
|
||||
(decl): decl is GrlOperationDeclaration => decl.kind === "OperationDeclaration"
|
||||
)!;
|
||||
|
||||
expect(operation).toMatchObject({
|
||||
kind: "OperationDeclaration",
|
||||
name: "weld_op_01",
|
||||
operationKind: "arc_welding",
|
||||
pathName: "weld_path",
|
||||
items: [
|
||||
{ kind: "OperationProcessBlock" },
|
||||
{ kind: "OperationActionBlock", actionKind: "start_action" },
|
||||
{ kind: "OperationActionBlock", actionKind: "end_action" }
|
||||
]
|
||||
});
|
||||
});
|
||||
|
||||
it("compiles operation process metadata and action statements", () => {
|
||||
const decls = declarations();
|
||||
const operation = decls.find((decl): decl is GrlOperationDeclaration => decl.kind === "OperationDeclaration")!;
|
||||
const paths = decls.filter((decl): decl is GrlPathDeclaration => decl.kind === "PathDeclaration");
|
||||
const compiled = compileOperation(operation, pathsByName(paths));
|
||||
|
||||
expect(compiled).toMatchObject({
|
||||
operationId: "weld_op_01",
|
||||
kind: "arc_welding",
|
||||
pathId: "weld_path",
|
||||
process: {
|
||||
weld_id: "WELD_1",
|
||||
voltage: 24,
|
||||
current: 180,
|
||||
weave: "none"
|
||||
},
|
||||
startActions: [
|
||||
{
|
||||
kind: "ACTION",
|
||||
actionKind: "start_action",
|
||||
operationId: "weld_op_01",
|
||||
statement: "io . do [ 20 ] = true"
|
||||
}
|
||||
],
|
||||
endActions: [
|
||||
{
|
||||
kind: "ACTION",
|
||||
actionKind: "end_action",
|
||||
operationId: "weld_op_01",
|
||||
statement: "io . do [ 20 ] = false"
|
||||
}
|
||||
]
|
||||
});
|
||||
});
|
||||
|
||||
it("extracts run_operation and expands to start action, path, and end action", () => {
|
||||
const decls = declarations();
|
||||
const procedure = decls.find((decl): decl is GrlProcedureDeclaration => decl.kind === "ProcedureDeclaration")!;
|
||||
const operation = decls.find((decl): decl is GrlOperationDeclaration => decl.kind === "OperationDeclaration")!;
|
||||
const paths = decls.filter((decl): decl is GrlPathDeclaration => decl.kind === "PathDeclaration");
|
||||
const compiled = compileOperation(operation, pathsByName(paths));
|
||||
const [run] = parseProcedureRunOperationStatements(procedure);
|
||||
|
||||
expect(run).toEqual({
|
||||
kind: "RUN_OPERATION",
|
||||
operationId: "weld_op_01",
|
||||
sourceMap: {
|
||||
line: 25,
|
||||
column: 5
|
||||
}
|
||||
});
|
||||
expect(expandRunOperation(run!, new Map([[compiled.operationId, compiled]]))).toEqual([
|
||||
expect.objectContaining({ kind: "ACTION", actionKind: "start_action" }),
|
||||
{
|
||||
kind: "RUN_PATH",
|
||||
pathId: "weld_path",
|
||||
sourceMap: {
|
||||
line: 25,
|
||||
column: 5
|
||||
}
|
||||
},
|
||||
expect.objectContaining({ kind: "ACTION", actionKind: "end_action" })
|
||||
]);
|
||||
});
|
||||
|
||||
it("reports operations that reference missing paths and missing run_operation targets", () => {
|
||||
const missingPathOperation = parseGrl(`language grl 0.1
|
||||
module Main
|
||||
operation bad_op {
|
||||
kind: handling
|
||||
path: missing_path
|
||||
}
|
||||
end
|
||||
`).module.declarations.find((decl): decl is GrlOperationDeclaration => decl.kind === "OperationDeclaration")!;
|
||||
|
||||
expect(() => compileOperation(missingPathOperation, new Map())).toThrowError(
|
||||
expect.objectContaining({ code: "GRL_OPERATION_PATH_NOT_FOUND" })
|
||||
);
|
||||
|
||||
expect(() =>
|
||||
expandRunOperation({ kind: "RUN_OPERATION", operationId: "missing_op" }, new Map())
|
||||
).toThrowError(expect.objectContaining({ code: "GRL_OPERATION_NOT_FOUND" }));
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user