Skip to content

Commit 47c00ec

Browse files
✨ Deploy AutoStep Feature
2 parents bfb45f0 + 6c791ee commit 47c00ec

File tree

9 files changed

+251
-38
lines changed

9 files changed

+251
-38
lines changed

src/application.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,13 +84,13 @@ export default class C0VMApplication extends React.Component<
8484
{SettingMenuComponent}
8585
{MainControlBarComponent}
8686
<Row className="main-ui-framework">
87-
<Col xs={24} sm={24} lg={12} xxl={11}>
87+
<Col xs={24} sm={12} lg={12} xxl={11}>
8888
<CodeEditor
8989
app_state={this.state}
9090
set_app_state={(ns: any) => this.setState(ns)}
9191
/>
9292
</Col>
93-
<Col xs={24} sm={24} lg={12} xxl={13} className="io-area">
93+
<Col xs={24} sm={12} lg={12} xxl={13} className="io-area">
9494
{StandardOutputComponent}
9595
{DebugConsoleComponent}
9696
</Col>

src/components/code-editor.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,7 @@ export default class CodeEditor extends React.Component
204204
{ label: "BC0",value: "bc0"}
205205
]}
206206
defaultValue={this.state.mode}
207+
onChange={(value) => {this.setState({mode: value as "c0" | "bc0"})}}
207208
/>
208209
);
209210
}

src/components/debug_console/graphical_component/stack_node.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@ export default class C0StackFrameNode extends React.Component<NodeProps<C0StackF
2626
for (let i = 0; i < data.frame.V.length; i ++) {
2727
const to_be_rendered = data.frame.V[i];
2828
if (to_be_rendered !== undefined && data.frame.P.varName[i] !== undefined) {
29-
console.log(to_be_rendered.type, data.typedef);
3029
contents.push(<p key={"s-val-name-" + i} className="right-aligned"><code>{Type2String(to_be_rendered.type, data.typedef)} {data.frame.P.varName[i]}</code></p>);
3130
let render_content = undefined;
3231
if (TypeUtil.isValueType(to_be_rendered)) {

src/components/main-control-bar.tsx

Lines changed: 138 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
import React from "react";
1+
import React, { useEffect, useState } from "react";
22

3-
import { Button, Space, Tooltip } from "antd";
3+
import { Button, Dropdown, MenuProps, Space, Tooltip } from "antd";
44

5-
import { faBoltLightning, faPlay, faScrewdriverWrench, faStepForward, faUndo } from "@fortawesome/free-solid-svg-icons";
5+
import { faAngleDown, faBoltLightning, faClockRotateLeft, faPlay, faScrewdriverWrench, faStepForward, faUndo } from "@fortawesome/free-solid-svg-icons";
66
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
77

88
import * as VM from "../vm_core/vm_interface";
@@ -30,11 +30,23 @@ function RequiresRecompile(){
3030
);
3131
}
3232

33+
function convertC0Bpts(C0Editors: C0EditorTab[]): Set<string>{
34+
const c0BreakPoint = new Set<string>();
35+
for (let i = 0; i < C0Editors.length; i ++){
36+
for (const currentEditor of C0Editors)
37+
for (const bpts of currentEditor.breakpoints){
38+
c0BreakPoint.add(`${currentEditor.title}@${bpts.line}`);
39+
}
40+
}
41+
return c0BreakPoint;
42+
}
43+
3344
function MainControlBarFC(props: MainControlProps & ContextValue) {
3445
const appState = props.application_state;
3546
const is_bc0_valid = props.application_state.BC0SourceCode.toUpperCase().startsWith("C0 C0 FF EE");
3647

3748
const [abortSignal, abort, reset] = AbortRef();
49+
const [execMode, setExecMode] = useState<"Run"|"AutoStep">("Run");
3850

3951
const print_update = (str: string) => props.set_app_state((s) => {return {PrintoutValue: s.PrintoutValue + str}})
4052
const clear_print = () => props.set_app_state({PrintoutValue: ""})
@@ -62,6 +74,42 @@ function MainControlBarFC(props: MainControlProps & ContextValue) {
6274
else props.set_app_state({C0Runtime: new_runtime});
6375
}
6476

77+
const autoStep_c0runtime = async() =>{
78+
if (appState.contentChanged) {
79+
RequiresRecompile();
80+
return;
81+
}
82+
let init_state: undefined | C0VM_RT = undefined;
83+
//let new_runtime, can_continue = undefined;
84+
85+
if (appState.C0Runtime === undefined) {
86+
init_state = await VM.initialize(appState.BC0SourceCode, clear_print, appState.C0Editors, print_update, MEM_POOL_SIZE);
87+
if (init_state === undefined) return;
88+
} else {
89+
init_state = appState.C0Runtime;
90+
}
91+
92+
const c0BreakPoint = convertC0Bpts(appState.C0Editors);
93+
const bc0BreakPointArr = Array.from(appState.BC0BreakPoints).map(bp => bp.line);
94+
const bc0BreakPoints = new Set(bc0BreakPointArr);
95+
96+
if (init_state===undefined) return;
97+
98+
const autoStepFn = VM.autoStep(
99+
init_state as C0VM_RT,
100+
bc0BreakPoints,
101+
c0BreakPoint,
102+
abortSignal,
103+
props.application_state.c0_only,
104+
reset,
105+
print_update,
106+
s => props.set_app_state({C0Runtime: s}),
107+
() => props.set_app_state({C0Running: false})
108+
)
109+
110+
props.set_app_state({C0Running: true}, ()=>autoStepFn);
111+
}
112+
65113
const run_c0runtime = async () => {
66114
if (appState.contentChanged) {
67115
RequiresRecompile();
@@ -136,10 +184,33 @@ function MainControlBarFC(props: MainControlProps & ContextValue) {
136184
print_update,
137185
);
138186
};
139-
187+
140188
const compilebtn_disabled = appState.C0Running || appState.C0Editors[0].content === "";
141189
const stepbtn_disabled = (!is_bc0_valid) || appState.C0Running || appState.contentChanged;
142190
const runbtn_disabled = (!is_bc0_valid) || appState.C0Running || appState.contentChanged;
191+
const autostepbtn_disabled = (!is_bc0_valid) || appState.C0Running || appState.contentChanged;
192+
const execbtn_disabled = execMode === "Run" ? runbtn_disabled : autostepbtn_disabled;
193+
194+
function onKeyPressWrapper(e: KeyboardEvent): void{
195+
const is_action_key = e.key==="a" || e.key ==='r' || e.key==="s";
196+
if (autostepbtn_disabled && is_action_key && e.ctrlKey) {
197+
if (!is_bc0_valid) globalThis.MSG_EMITTER.warn("Action Unavailable","Invalid BC0 code.");
198+
else if(appState.C0Running) globalThis.MSG_EMITTER.warn("Action Unavailable","The program is currently running.");
199+
else if(appState.contentChanged) RequiresRecompile();
200+
}
201+
else if (e.ctrlKey) onKeyPress(e.key);
202+
}
203+
204+
function onKeyPress(key: string): void{
205+
if(key==='a') autoStep_c0runtime();
206+
else if(key==='r') run_c0runtime();
207+
else if(key==='s') step_c0runtime();
208+
}
209+
210+
useEffect(() =>{
211+
document.addEventListener('keydown', onKeyPressWrapper)
212+
return () => document.removeEventListener('keydown',onKeyPressWrapper);
213+
})
143214

144215
const CompileButton =
145216
<Button
@@ -162,16 +233,15 @@ function MainControlBarFC(props: MainControlProps & ContextValue) {
162233
&nbsp;Step
163234
</Button>;
164235

236+
const AutoStepButton =
237+
<div style={{fontSize: "1rem", color: "white"}}>
238+
<FontAwesomeIcon icon={faClockRotateLeft}/>&nbsp;AutoStep
239+
</div>;
240+
165241
const RunButton =
166-
<Button
167-
icon={<FontAwesomeIcon icon={faPlay}/>}
168-
size = "large"
169-
type = "primary"
170-
disabled={runbtn_disabled}
171-
onClick={run_c0runtime}
172-
>
173-
&nbsp;Run
174-
</Button>;
242+
<div style={{fontSize: "1rem", color: "white"}}>
243+
<FontAwesomeIcon icon={faPlay}/>&nbsp;Run
244+
</div>;
175245

176246
const AbortButton =
177247
<Button
@@ -193,17 +263,66 @@ function MainControlBarFC(props: MainControlProps & ContextValue) {
193263
&nbsp;Restart
194264
</Button>;
195265

266+
const ExecBtnIcon = execMode === "Run" ?
267+
<FontAwesomeIcon icon={faPlay}/> :
268+
<FontAwesomeIcon icon={faClockRotateLeft}/>;
269+
270+
const ExecBtnFn = execMode === "Run" ? run_c0runtime : autoStep_c0runtime;
271+
272+
const menuItems_ExecBtn: MenuProps["items"] = [
273+
{
274+
label: execMode === "Run" ? AutoStepButton : RunButton,
275+
key: execMode === "Run" ? "AutoStep" : "Run"
276+
}
277+
];
278+
279+
const menuItems_ChangeModeFn: MenuProps["onClick"] = (info) => {
280+
if (info.key === "Run" || info.key === "AutoStep") {
281+
setExecMode(info.key);
282+
}
283+
};
284+
285+
const MenuProp: MenuProps = {
286+
style: {backgroundColor: props.themeColor},
287+
items: menuItems_ExecBtn,
288+
onClick: menuItems_ChangeModeFn
289+
};
290+
291+
const ExecBtn =
292+
<Dropdown.Button
293+
disabled={execbtn_disabled}
294+
type="primary"
295+
size="large"
296+
icon={<FontAwesomeIcon icon={faAngleDown}/>}
297+
onClick={ExecBtnFn}
298+
menu={MenuProp}
299+
>
300+
{ExecBtnIcon}&nbsp;{execMode}
301+
</Dropdown.Button>;
302+
196303
const display_CompileBtn = compilebtn_disabled ?
197304
<Tooltip placement="bottomRight" color={props.themeColor} title="Write code in editor to Compile">{CompileButton}</Tooltip>
198305
: CompileButton;
199306

200307
const display_StepBtn = stepbtn_disabled ?
201-
<Tooltip placement="bottomRight" color={props.themeColor} title="Compile the code before Step">{StepButton}</Tooltip>
308+
<Tooltip
309+
placement="bottomRight"
310+
color={props.themeColor}
311+
title="Compile the code / Abort the program before Step"
312+
>
313+
{StepButton}
314+
</Tooltip>
202315
: StepButton;
203-
204-
const display_RunBtn = runbtn_disabled ?
205-
<Tooltip placement="bottomRight" color={props.themeColor} title="Compile the code before Run">{RunButton}</Tooltip>
206-
: RunButton;
316+
317+
const display_ExecBtn = execbtn_disabled ?
318+
<Tooltip
319+
placement="bottomRight"
320+
color={props.themeColor}
321+
title={"Compile the code / Abort the program before " + execMode}
322+
>
323+
{ExecBtn}
324+
</Tooltip>
325+
: ExecBtn;
207326

208327
return (
209328
<div className="main-control">
@@ -213,7 +332,7 @@ function MainControlBarFC(props: MainControlProps & ContextValue) {
213332
<Space size="middle">
214333
{display_CompileBtn}
215334
{display_StepBtn}
216-
{display_RunBtn}
335+
{display_ExecBtn}
217336
{appState.C0Running ? AbortButton : RestartButton}
218337
</Space>
219338
</div>

src/components/settings.tsx

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { faAngleDown, faAngleRight, faGear } from "@fortawesome/free-solid-svg-icons";
22
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
3-
import { Switch, Modal, Button } from "antd";
3+
import { Switch, Modal, Button, Select } from "antd";
44
import React from "react";
55

66
export default class SettingPopup extends React.Component<SettingMenuProps> {
@@ -19,14 +19,37 @@ export default class SettingPopup extends React.Component<SettingMenuProps> {
1919
style={{maxHeight: "80vh", overflowY: "auto"}}
2020
>
2121
<div className="settings-grid">
22-
<p>Contract Check (<code>-d</code> Flag)</p> <Switch size="small" style={{justifySelf: "right"}} defaultChecked={this.props.state.CompilerFlags['d']} onChange={() => {
22+
<p>Contract Check (<code>-d</code> Flag)</p>
23+
<Switch
24+
size="small"
25+
style={{justifySelf: "right"}}
26+
defaultChecked={this.props.state.CompilerFlags['d']}
27+
onChange={() => {
2328
this.props.set_app_state((state) => {
2429
return {CompilerFlags: {...state.CompilerFlags,
2530
d: !state.CompilerFlags["d"]}
2631
}
2732
});
2833
}}/>
29-
<p>Expose Bytecode</p> <Switch size="small" style={{justifySelf: "right"}} defaultChecked={!this.props.state.c0_only} onChange={() => {this.props.set_app_state((state) => {return {c0_only: !state.c0_only}})}}/>
34+
35+
<p>Expose Bytecode</p>
36+
<Switch size="small" style={{justifySelf: "right"}} defaultChecked={!this.props.state.c0_only} onChange={() => {this.props.set_app_state((state) => {return {c0_only: !state.c0_only}})}}/>
37+
38+
<p>AutoStep Speed</p>
39+
<Select
40+
size="small"
41+
defaultValue={globalThis.AUTOSTEP_INTERVAL}
42+
options={[
43+
{value: "Fast", label: "Fast (0.5 s)"},
44+
{value: "Slow", label: "Slow (1.5 s)"}
45+
]}
46+
onChange={
47+
(value: string) => {
48+
if (value === "Fast" || value === "Slow") globalThis.AUTOSTEP_INTERVAL = value;
49+
}
50+
}
51+
/>
52+
3053
<AdvancedSetting {...this.props}/>
3154
</div>
3255
</Modal>

src/index.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import C0VMApplication from './application';
1111
import AntdEmitter from './utility/antd_emitter';
1212

1313
// Global Variables
14-
global.C0VM_VERSION = "0.3.2-Beta";
14+
global.C0VM_VERSION = "0.3.3-Beta";
1515

1616
globalThis.DEBUG = true;
1717
globalThis.DEBUG_DUMP_MEM = false;
@@ -35,6 +35,7 @@ globalThis.COMPILER_BACKEND_URL = "https://cs122.andrew.cmu.edu/visualc0/compile
3535
globalThis.C0_MAX_RECURSION = 999;
3636
globalThis.C0_TIME_SLICE = 500;
3737
globalThis.C0_ASYNC_INTERVAL = 1;
38+
globalThis.AUTOSTEP_INTERVAL = "Slow";
3839

3940
if (globalThis.MSG_EMITTER === undefined) {
4041
globalThis.MSG_EMITTER = new AntdEmitter();

src/types/global-var.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ declare global {
2121
var C0_TIME_SLICE: number; // Number of steps the C0VM can go in a continuous time slice
2222
// (after this #step, the control flow will be handled back to UI/main event loop to keep page responsive)
2323
var C0_ASYNC_INTERVAL: number; // Interval between each time slice will be at least these much ms
24+
var AUTOSTEP_INTERVAL: "Fast" | "Slow"; // Interval between each step during AUTOSTEP, in ms
2425

2526
// MS Clarity client API
2627
var clarity: undefined | ((s: "set", key: "VM Error",

src/types/react-interface.d.ts

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -32,23 +32,23 @@ interface C0VMApplicationProps {
3232
}
3333

3434
interface C0VMApplicationState {
35-
crashed : boolean, /* C0VM Application top-level error boundary */
36-
c0_only : boolean, /* C0 only mode or not */
37-
contentChanged : boolean, /* If content has changed or not (requires re-compile) */
38-
dbgFullScreen : boolean, /* If it is in full screen mode currently */
39-
settingMenuOn : boolean, /* See if the setting menu is on or not */
35+
crashed : boolean, /* C0VM Application top-level error boundary */
36+
c0_only : boolean, /* C0 only mode or not */
37+
contentChanged : boolean, /* If content has changed or not (requires re-compile) */
38+
dbgFullScreen : boolean, /* If it is in full screen mode currently */
39+
settingMenuOn : boolean, /* See if the setting menu is on or not */
4040

41-
BC0SourceCode : string, /* The content of BC0 code editor */
42-
BC0BreakPoints : Set<BreakPoint>, /* Breakpoints activated in BC0 code editor */
41+
BC0SourceCode : string, /* The content of BC0 code editor */
42+
BC0BreakPoints : Set<BreakPoint>, /* Breakpoints activated in BC0 code editor */
4343

44-
C0Editors : C0EditorTab[], /* Code editor tab titles */
45-
ActiveEditor : number, /* Currently activated tab index of C0Editor */
44+
C0Editors : C0EditorTab[], /* Code editor tab titles */
45+
ActiveEditor : number, /* Currently activated tab index of C0Editor */
4646

47-
PrintoutValue : string, /* The string to show in the stdout console */
47+
PrintoutValue : string, /* The string to show in the stdout console */
4848

49-
C0Running : boolean, /* If the C0VM is running currently */
49+
C0Running : boolean, /* If the C0VM is running currently */
5050
C0Runtime : C0VM_RT | undefined, /* Runtime of C0VM */
51-
CompilerFlags : Record<string, boolean> /* Compiler Flags (-d) */
51+
CompilerFlags : Record<string, boolean> /* Compiler Flags (-d) */
5252
};
5353

5454

0 commit comments

Comments
 (0)