Skip to content

Commit

Permalink
opslang: duration type and wait statement
Browse files Browse the repository at this point in the history
  • Loading branch information
kobkaz committed Jan 22, 2024
1 parent a9b25b8 commit 6792f98
Show file tree
Hide file tree
Showing 5 changed files with 266 additions and 90 deletions.
81 changes: 48 additions & 33 deletions tmtc-c2a/devtools_frontend/src/components/CommandView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import {
import { Tco, TcoParam, TmivField } from "../proto/tco_tmiv";
import { useClient } from "./Layout";
import { GrpcClientService } from "../worker";
import init, * as opslang from "../../wasm-opslang/pkg";
import initOpslang, * as opslang from "../../wasm-opslang/pkg";

type ParameterValue =
| { type: "bytes"; bytes: Uint8Array; bigint: bigint }
Expand Down Expand Up @@ -242,10 +242,6 @@ class Driver implements opslang.Driver {
});
}

async waitMilliseconds(msecs: number): Promise<void> {
return new Promise((resolve) => setTimeout(() => resolve(), msecs));
}

resolveVariable(name: string): opslang.Value | undefined {
const local = this.localVariables.get(name);
if (local !== undefined) {
Expand Down Expand Up @@ -280,6 +276,8 @@ class Driver implements opslang.Driver {
return String(value.value);
} else if (value.kind === "array") {
return `[${value.value.map(toStr).join(", ")}]`;
} else if (value.kind === "duration") {
return `${value.value}ms`;
}
return JSON.stringify(value.value);
};
Expand Down Expand Up @@ -318,7 +316,8 @@ export const CommandView: React.FC = () => {
useEffect(() => {
(async () => {
// init opslang
await init();
await initOpslang();
opslang.set_panic_hook();
})();
}, []);
const {
Expand Down Expand Up @@ -396,52 +395,51 @@ export const CommandView: React.FC = () => {
};

type ExecuteLineResult =
| { success: true; status: opslang.ControlStatus }
| {
success: true;
status: opslang.ControlStatus;
executionContext: opslang.ExecutionContext | undefined;
}
| { success: false; error: unknown };
const executeLine = async (
line: string,
isFirstLine: boolean,
): Promise<ExecuteLineResult> => {
try {
await driver.prepareVariables(opslang.freeVariables(line));
const status = await opslang.executeLine(driver, line, !isFirstLine);
return { success: true, status };
} catch (error) {
return { success: false, error };
}
};

const executeLineParsed = async (
parsed: opslang.ParsedCode,
context: opslang.ExecutionContext | undefined,
lineNum: number,
isFirstLine: boolean,
): Promise<ExecuteLineResult> => {
try {
await driver.prepareVariables(parsed.freeVariables(lineNum));
const status = await parsed.executeLine(
const result = await parsed.executeLine(
driver,
context,
!isFirstLine,
lineNum,
Date.now(),
);
return { success: true, status };
const status = result.status;
const executionContext = result.execution_context;
result.free();
return { success: true, status, executionContext };
} catch (error) {
return { success: false, error };
}
};

const processLine = async (
firstLine: number,
initialLine: number,
parsed: opslang.ParsedCode,
): Promise<boolean> => {
executionContext: opslang.ExecutionContext | undefined,
): Promise<[boolean, opslang.ExecutionContext | undefined]> => {
const model = editor.getModel();
if (model === null) {
return false;
return [false, executionContext];
}
localStorage.setItem("c2a-devtools-ops-v1", editor.getValue());

const position = editor.getPosition();
if (position === null) {
return false;
return [false, executionContext];
}
const lineno = position.lineNumber;

Expand All @@ -460,10 +458,13 @@ export const CommandView: React.FC = () => {
},
]);

// executionContext will be "moved" here
// executionContext cannot be used after this call
const result = await executeLineParsed(
parsed,
executionContext,
lineno,
lineno == firstLine,
lineno == initialLine,
);
if (!result.success) {
decoration.clear();
Expand All @@ -488,10 +489,11 @@ export const CommandView: React.FC = () => {
endColumn: model.getLineLength(lineno) + 1,
},
]);
return false;
return [false, undefined];
}

if (result.status === opslang.ControlStatus.Breaked) {
return false;
return [false, result.executionContext];
}
if (result.status === opslang.ControlStatus.Executed) {
decoration.clear();
Expand All @@ -507,15 +509,15 @@ export const CommandView: React.FC = () => {
},
]);
if (lineno >= model.getLineCount()) {
return false;
return [false, result.executionContext];
}
const nextPosition = new monaco.Position(lineno + 1, 1);
editor.setPosition(nextPosition);
editor.revealLine(lineno + 1);
}
const delay = new Promise((resolve) => setTimeout(resolve, 250));
await delay;
return true;
return [true, result.executionContext];
};

editor.addCommand(
Expand All @@ -526,9 +528,22 @@ export const CommandView: React.FC = () => {
return;
}
const parsed = opslang.ParsedCode.fromCode(editor.getValue());
const firstLine = position.lineNumber;
while (await processLine(firstLine, parsed)) {
/* do nothing */
const initialLine = position.lineNumber;
let executionContext: opslang.ExecutionContext | undefined =
undefined;

// eslint-disable-next-line no-constant-condition
while (true) {
const [cont, nextExecutionContext] = await processLine(
initialLine,
parsed,
executionContext,
);
executionContext = nextExecutionContext;
if (!cont) {
executionContext?.free();
break;
}
}
parsed.free();
},
Expand Down
1 change: 1 addition & 0 deletions tmtc-c2a/devtools_frontend/wasm-opslang/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ async-recursion = "*"
# all the `std::fmt` and `std::panicking` infrastructure, so isn't great for
# code size when deploying.
console_error_panic_hook = { version = "0.1.7", optional = true }
chrono = "0.4.31"

[dev-dependencies]
wasm-bindgen-test = "0.3.34"
Expand Down
2 changes: 2 additions & 0 deletions tmtc-c2a/devtools_frontend/wasm-opslang/js/union.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ export const asDouble = asKind("double");
export const asBool = asKind("bool");
export const asArray = asKind("array");
export const asString = asKind("string");
export const asDuration = asKind("duration");

const make = (kind) => {
return (value) => {
Expand All @@ -28,3 +29,4 @@ export const makeDouble = make("double");
export const makeBool = make("bool");
export const makeArray = make("array");
export const makeString = make("string");
export const makeDuration = make("duration");
Loading

0 comments on commit 6792f98

Please sign in to comment.