增加解释器WASM命名参数夹具
结论:解释器核心WASM新增带INI文件边界的运行入口,并覆盖namedparam_semantics夹具,INI/HAL解析继续直接来自LinuxCNC解释器源码。
This commit is contained in:
@@ -198,11 +198,12 @@ INI parser smoke harness and an initial interpreter-core canonical event smoke
|
||||
for `minimal_linear`, `arc_semantics`, `length_units`, `modal_incremental`,
|
||||
`plane_selection`, `coordinate_offsets`, `g53_machine_coordinates`,
|
||||
`feed_control_modes`, `position_params`, `probe_semantics`, `spindle_orient`,
|
||||
`comment_logging`, and `numbered_params`, plus the `g1_zero_feed`,
|
||||
`arc_radius_mismatch`, `arc_zero_radius`, and `g53_incremental` negative
|
||||
fixtures. The WASM interpreter file path additionally covers
|
||||
`file_open_reset`, `percent_file_finish`, and `oword_subroutine`. OPFS
|
||||
validation is limited to the JavaScript host-boundary adapter plus the INI
|
||||
`comment_logging`, `numbered_params`, and `namedparam_semantics`, plus the
|
||||
`g1_zero_feed`, `arc_radius_mismatch`, `arc_zero_radius`, and
|
||||
`g53_incremental` negative fixtures. The WASM interpreter file path
|
||||
additionally covers `file_open_reset`, `percent_file_finish`, and
|
||||
`oword_subroutine`. OPFS validation is limited to the JavaScript host-boundary
|
||||
adapter plus the INI
|
||||
browser smoke harness. Full browser coverage, full SDK coverage, and full
|
||||
machine-session validation remain future work.
|
||||
|
||||
|
||||
@@ -131,8 +131,14 @@ void append_events_and_state(std::ostringstream &output, const Interp &interp)
|
||||
extern "C" {
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE
|
||||
char *lcinterp_run_program(const char *program_text)
|
||||
char *lcinterp_run_program_with_ini(const char *program_text, const char *ini_path)
|
||||
{
|
||||
if (ini_path && ini_path[0] != '\0') {
|
||||
setenv("INI_FILE_NAME", ini_path, 1);
|
||||
} else {
|
||||
unsetenv("INI_FILE_NAME");
|
||||
}
|
||||
|
||||
Interp interp;
|
||||
standalone::reset_canon_events();
|
||||
initialize_minimal_interp(interp);
|
||||
@@ -160,9 +166,17 @@ char *lcinterp_run_program(const char *program_text)
|
||||
return copy_result(output.str());
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE
|
||||
char *lcinterp_run_program(const char *program_text)
|
||||
{
|
||||
return lcinterp_run_program_with_ini(program_text, nullptr);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE
|
||||
char *lcinterp_run_file(const char *path)
|
||||
{
|
||||
unsetenv("INI_FILE_NAME");
|
||||
|
||||
Interp interp;
|
||||
standalone::reset_canon_events();
|
||||
initialize_minimal_interp(interp);
|
||||
|
||||
@@ -27,6 +27,23 @@ function runProgram(mod, programText) {
|
||||
}
|
||||
}
|
||||
|
||||
function runProgramWithIni(mod, programText, iniPath) {
|
||||
const programPtr = allocCString(mod, programText);
|
||||
const iniPathPtr = allocCString(mod, iniPath);
|
||||
let resultPtr = 0;
|
||||
try {
|
||||
resultPtr = mod._lcinterp_run_program_with_ini(programPtr, iniPathPtr);
|
||||
assert.notEqual(resultPtr, 0);
|
||||
return mod.UTF8ToString(resultPtr);
|
||||
} finally {
|
||||
if (resultPtr) {
|
||||
mod._lcinterp_free_string(resultPtr);
|
||||
}
|
||||
mod._free(programPtr);
|
||||
mod._free(iniPathPtr);
|
||||
}
|
||||
}
|
||||
|
||||
function ensureDir(mod, path) {
|
||||
try {
|
||||
mod.FS.mkdir(path);
|
||||
@@ -114,6 +131,27 @@ for (const fixtureName of fixtureNames) {
|
||||
verifyExpectedOutput(fixtureName, runProgram(interp, programText), expectedEvents);
|
||||
}
|
||||
|
||||
ensureDir(interp, "/work");
|
||||
const namedParamIniPath = "/work/namedparams.ini";
|
||||
interp.FS.writeFile(
|
||||
namedParamIniPath,
|
||||
readFileSync(resolve(rootDir, "tests/fixtures/ini/namedparams.ini"), "utf8"),
|
||||
{ encoding: "utf8" },
|
||||
);
|
||||
const namedParamProgramText = readFileSync(
|
||||
resolve(rootDir, "tests/fixtures/gcode/namedparam_semantics.ngc"),
|
||||
"utf8",
|
||||
);
|
||||
const namedParamExpected = readFileSync(
|
||||
resolve(rootDir, "tests/fixtures/canon/namedparam_semantics.events"),
|
||||
"utf8",
|
||||
).trimEnd();
|
||||
verifyExpectedOutput(
|
||||
"namedparam_semantics",
|
||||
runProgramWithIni(interp, namedParamProgramText, namedParamIniPath),
|
||||
namedParamExpected,
|
||||
);
|
||||
|
||||
const errorFixtureNames = [
|
||||
"g1_zero_feed",
|
||||
"arc_radius_mismatch",
|
||||
@@ -140,7 +178,6 @@ const fileFixtureNames = [
|
||||
"oword_subroutine",
|
||||
];
|
||||
|
||||
ensureDir(interp, "/work");
|
||||
for (const fixtureName of fileFixtureNames) {
|
||||
const programPath = `/work/${fixtureName}.ngc`;
|
||||
const programText = readFileSync(
|
||||
|
||||
@@ -95,5 +95,5 @@ link_wasm_module \
|
||||
-s STACK_SIZE=2MB \
|
||||
-s NO_EXIT_RUNTIME=1 \
|
||||
-s FORCE_FILESYSTEM=1 \
|
||||
-s EXPORTED_FUNCTIONS='["_malloc","_free","_lcinterp_run_program","_lcinterp_run_file","_lcinterp_free_string"]' \
|
||||
-s EXPORTED_FUNCTIONS='["_malloc","_free","_lcinterp_run_program","_lcinterp_run_program_with_ini","_lcinterp_run_file","_lcinterp_free_string"]' \
|
||||
-s EXPORTED_RUNTIME_METHODS='["FS","UTF8ToString","stringToUTF8","lengthBytesUTF8"]'
|
||||
|
||||
Reference in New Issue
Block a user