Skip to content

update frontend for scheme data visualisation #2916

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 29 commits into from
Apr 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
a89a7fc
Switch Scheme languages fully to CSE Machine
s-kybound Feb 20, 2024
e5be9f5
Merge branch 'source/master' into 'master'
s-kybound Feb 20, 2024
93f6df2
Updated tests with windows machine
s-kybound Feb 20, 2024
12ebcfe
Ran tests on different windows machine
s-kybound Feb 20, 2024
bf3770d
Merge branch 'master' into master
RichDom2185 Feb 20, 2024
ed1b9e7
Merge branch 'source/master'
s-kybound Mar 18, 2024
ad7c991
Merge branch 'sourceMaster'
s-kybound Mar 21, 2024
c7611a5
Merge branch 'source-academy:master' into master
s-kybound Mar 21, 2024
9506b82
Merge remote-tracking branch 'origin/master'
s-kybound Mar 21, 2024
7cf1c0e
Merge branch 'source-academy:master' into master
s-kybound Apr 3, 2024
8155879
resolve all issues with scheme CSE machine
s-kybound Apr 4, 2024
d1ae389
update tests
s-kybound Apr 4, 2024
a647a15
merge origin/master into master
s-kybound Apr 4, 2024
cb4d0e4
reenable csc machine for scheme
s-kybound Apr 4, 2024
c37f834
add prototype visualisations for scheme data types
s-kybound Apr 8, 2024
d52a402
Merge branch 'sourceMaster'
s-kybound Apr 8, 2024
005d824
update tests
s-kybound Apr 8, 2024
f561bbc
simplify logic for checking prelude
s-kybound Apr 8, 2024
236fafd
Merge branch 'master' into master
martin-henz Apr 9, 2024
3f3678c
Merge branch 'sourceMaster'
s-kybound Apr 9, 2024
9fb1c84
Make cse refer to correct closure
s-kybound Apr 14, 2024
8ae2bf5
Centralise logic for alternate languages
s-kybound Apr 14, 2024
4946e19
separate scheme as its own file
s-kybound Apr 14, 2024
732c4ac
add scheme primitive representation to cse machine
s-kybound Apr 14, 2024
cf02879
update representation of control
s-kybound Apr 14, 2024
b3c6906
Merge branch 'master' of https://github.com/s-kybound/frontend
s-kybound Apr 14, 2024
83dd88c
Squashed commit of the following:
s-kybound Apr 14, 2024
8cb7c61
update tests
s-kybound Apr 14, 2024
3880b87
merge source/master into master
s-kybound Apr 14, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 15 additions & 1 deletion src/commons/application/ApplicationTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -198,9 +198,23 @@ const schemeSubLanguages: Array<Pick<SALanguage, 'chapter' | 'variant' | 'displa
];

export const schemeLanguages: SALanguage[] = schemeSubLanguages.map(sublang => {
return { ...sublang, mainLanguage: SupportedLanguage.SCHEME, supports: { repl: true } };
return {
...sublang,
mainLanguage: SupportedLanguage.SCHEME,
supports: { repl: true, cseMachine: true }
};
});

export function isSchemeLanguage(chapter: Chapter): boolean {
return [
Chapter.SCHEME_1,
Chapter.SCHEME_2,
Chapter.SCHEME_3,
Chapter.SCHEME_4,
Chapter.FULL_SCHEME
].includes(chapter);
}

const pySubLanguages: Array<Pick<SALanguage, 'chapter' | 'variant' | 'displayName'>> = [
{ chapter: Chapter.PYTHON_1, variant: Variant.DEFAULT, displayName: 'Python \xa71' }
//{ chapter: Chapter.PYTHON_2, variant: Variant.DEFAULT, displayName: 'Python \xa72' },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ Array [
"displayName": "Scheme §1",
"mainLanguage": "Scheme",
"supports": Object {
"cseMachine": true,
"repl": true,
},
"variant": "explicit-control",
Expand All @@ -30,6 +31,7 @@ Array [
"displayName": "Scheme §2",
"mainLanguage": "Scheme",
"supports": Object {
"cseMachine": true,
"repl": true,
},
"variant": "explicit-control",
Expand All @@ -39,6 +41,7 @@ Array [
"displayName": "Scheme §3",
"mainLanguage": "Scheme",
"supports": Object {
"cseMachine": true,
"repl": true,
},
"variant": "explicit-control",
Expand All @@ -48,6 +51,7 @@ Array [
"displayName": "Scheme §4",
"mainLanguage": "Scheme",
"supports": Object {
"cseMachine": true,
"repl": true,
},
"variant": "explicit-control",
Expand All @@ -57,6 +61,7 @@ Array [
"displayName": "Full Scheme",
"mainLanguage": "Scheme",
"supports": Object {
"cseMachine": true,
"repl": true,
},
"variant": "explicit-control",
Expand Down
6 changes: 5 additions & 1 deletion src/commons/sagas/PlaygroundSaga.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import {
updateShortURL
} from '../../features/playground/PlaygroundActions';
import { GENERATE_LZ_STRING, SHORTEN_URL } from '../../features/playground/PlaygroundTypes';
import { isSourceLanguage, OverallState } from '../application/ApplicationTypes';
import { isSchemeLanguage, isSourceLanguage, OverallState } from '../application/ApplicationTypes';
import { ExternalLibraryName } from '../application/types/ExternalTypes';
import { retrieveFilesInWorkspaceAsRecord } from '../fileSystem/utils';
import { visitSideContent } from '../sideContent/SideContentActions';
Expand Down Expand Up @@ -122,6 +122,10 @@ export default function* PlaygroundSaga(): SagaIterator {
yield put(toggleUsingCse(true, workspaceLocation));
}
}

if (isSchemeLanguage(playgroundSourceChapter) && newId === SideContentType.cseMachine) {
yield put(toggleUsingCse(true, workspaceLocation));
}
}
);
}
Expand Down
5 changes: 3 additions & 2 deletions src/commons/sagas/WorkspaceSaga/helpers/evalCode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import { notifyStoriesEvaluated } from 'src/features/stories/StoriesActions';
import { EVAL_STORY } from 'src/features/stories/StoriesTypes';

import { EventType } from '../../../../features/achievement/AchievementTypes';
import { OverallState } from '../../../application/ApplicationTypes';
import { isSchemeLanguage, OverallState } from '../../../application/ApplicationTypes';
import {
BEGIN_DEBUG_PAUSE,
BEGIN_INTERRUPT_EXECUTION,
Expand Down Expand Up @@ -95,7 +95,8 @@ export function* evalCode(
.currentStep
)
: -1;
const cseActiveAndCorrectChapter = context.chapter >= 3 && cseIsActive;
const cseActiveAndCorrectChapter =
(isSchemeLanguage(context.chapter) || context.chapter >= 3) && cseIsActive;
if (cseActiveAndCorrectChapter) {
context.executionMethod = 'cse-machine';
}
Expand Down
3 changes: 2 additions & 1 deletion src/features/cseMachine/CseMachine.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,8 @@ export default class CseMachine {
Layout.setContext(
context.runtime.environmentTree as EnvTree,
context.runtime.control,
context.runtime.stash
context.runtime.stash,
context.chapter
);
this.setVis(Layout.draw());
this.setIsStepLimitExceeded(context.runtime.control.isEmpty());
Expand Down
19 changes: 12 additions & 7 deletions src/features/cseMachine/CseMachineLayout.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import Heap from 'js-slang/dist/cse-machine/heap';
import { Control, Stash } from 'js-slang/dist/cse-machine/interpreter';
import { Frame } from 'js-slang/dist/types';
import { Chapter, Frame } from 'js-slang/dist/types';
import { KonvaEventObject } from 'konva/lib/Node';
import React, { RefObject } from 'react';
import { Layer, Rect, Stage } from 'react-konva';
Expand Down Expand Up @@ -137,7 +137,12 @@ export class Layout {
}

/** processes the runtime context from JS Slang */
static setContext(envTree: EnvTree, control: Control, stash: Stash): void {
static setContext(
envTree: EnvTree,
control: Control,
stash: Stash,
chapter: Chapter = Chapter.SOURCE_4
): void {
Layout.currentLight = undefined;
Layout.currentDark = undefined;
Layout.currentStackDark = undefined;
Expand All @@ -160,7 +165,7 @@ export class Layout {
// initialize levels and frames
Layout.initializeGrid();
// initialize control and stash
Layout.initializeControlStash();
Layout.initializeControlStash(chapter);

if (CseMachine.getControlStash()) {
Layout.controlStashHeight = Math.max(
Expand Down Expand Up @@ -193,19 +198,19 @@ export class Layout {
CseAnimation.updateAnimation();
}

static initializeControlStash() {
static initializeControlStash(chapter: Chapter) {
Layout.previousControlComponent = Layout.controlComponent;
Layout.previousStashComponent = Layout.stashComponent;
this.controlComponent = new ControlStack(this.control);
this.stashComponent = new StashStack(this.stash);
this.controlComponent = new ControlStack(this.control, chapter);
this.stashComponent = new StashStack(this.stash, chapter);
}

/**
* remove prelude environment containing predefined functions, by merging the prelude
* objects into the global environment head and heap
*/
private static removePreludeEnv() {
if (!Layout.globalEnvNode.children) return;
if (!Layout.globalEnvNode.children || Layout.globalEnvNode.children.length === 0) return;

const preludeEnvNode = Layout.globalEnvNode.children[0];
const preludeEnv = preludeEnvNode.environment;
Expand Down
68 changes: 63 additions & 5 deletions src/features/cseMachine/CseMachineUtils.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { estreeDecode } from 'js-slang/dist/alt-langs/scheme/scm-slang/src/utils/encoder-visitor';
import { unparse } from 'js-slang/dist/alt-langs/scheme/scm-slang/src/utils/reverse_parser';
import JsSlangClosure from 'js-slang/dist/cse-machine/closure';
import {
AppInstr,
Expand All @@ -10,13 +12,14 @@ import {
InstrType,
UnOpInstr
} from 'js-slang/dist/cse-machine/types';
import { Environment, Value as StashValue } from 'js-slang/dist/types';
import { Chapter, Environment, Value as StashValue } from 'js-slang/dist/types';
import { astToString } from 'js-slang/dist/utils/ast/astToString';
import { Group } from 'konva/lib/Group';
import { Node } from 'konva/lib/Node';
import { Shape } from 'konva/lib/Shape';
import { Text } from 'konva/lib/shapes/Text';
import { cloneDeep, isObject } from 'lodash';
import { isSchemeLanguage } from 'src/commons/application/ApplicationTypes';
import classes from 'src/styles/Draggable.module.scss';

import { ArrayUnit } from './components/ArrayUnit';
Expand Down Expand Up @@ -49,7 +52,11 @@ import {
StreamFn,
Unassigned
} from './CseMachineTypes';

import {
getAlternateControlItemComponent,
isCustomPrimitive,
needsNewRepresentation
} from './utils/altLangs';
class AssertionError extends Error {
constructor(msg?: string) {
super(msg);
Expand Down Expand Up @@ -195,7 +202,8 @@ export function isPrimitiveData(data: Data): data is Primitive {
isString(data) ||
isNumber(data) ||
isBoolean(data) ||
isSourceObject(data)
isSourceObject(data) ||
isCustomPrimitive(data)
);
}

Expand Down Expand Up @@ -568,12 +576,39 @@ export function getControlItemComponent(
stackHeight: number,
index: number,
highlightOnHover: () => void,
unhighlightOnHover: () => void
unhighlightOnHover: () => void,
chapter: Chapter
): ControlItemComponent {
const topItem = CseMachine.getStackTruncated()
? index === Math.min(Layout.control.size() - 1, 9)
: index === Layout.control.size() - 1;
if (!isInstr(controlItem)) {
// there's no reason to provide an alternate representation
// for a instruction.
if (needsNewRepresentation(chapter)) {
return getAlternateControlItemComponent(
controlItem,
stackHeight,
highlightOnHover,
unhighlightOnHover,
topItem,
chapter
);
}

if (isSchemeLanguage(chapter)) {
// use the js-slang decoder on the control item
controlItem = estreeDecode(controlItem as any);
const text = unparse(controlItem as any);
return new ControlItemComponent(
text,
text,
stackHeight,
highlightOnHover,
unhighlightOnHover,
topItem
);
}
switch (controlItem.type) {
case 'Program':
// If the control item is the whole program
Expand Down Expand Up @@ -792,6 +827,24 @@ export function getControlItemComponent(
unhighlightOnHover,
topItem
);
case InstrType.GENERATE_CONT:
return new ControlItemComponent(
'generate cont',
'Generate continuation',
stackHeight,
highlightOnHover,
unhighlightOnHover,
topItem
);
case InstrType.RESUME_CONT:
return new ControlItemComponent(
'call cont',
'call a continuation',
stackHeight,
highlightOnHover,
unhighlightOnHover,
topItem
);
default:
return new ControlItemComponent(
'INSTRUCTION',
Expand All @@ -805,7 +858,12 @@ export function getControlItemComponent(
}
}

export function getStashItemComponent(stashItem: StashValue, stackHeight: number, index: number) {
export function getStashItemComponent(
stashItem: StashValue,
stackHeight: number,
index: number,
_chapter: Chapter
): StashItemComponent {
let arrowTo: ArrayValue | FnValue | GlobalFnValue | undefined;
if (isFunction(stashItem) || isDataArray(stashItem)) {
if (isClosure(stashItem) || isDataArray(stashItem)) {
Expand Down
10 changes: 7 additions & 3 deletions src/features/cseMachine/components/ControlStack.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Control } from 'js-slang/dist/cse-machine/interpreter';
import { ControlItem, Instr } from 'js-slang/dist/cse-machine/types';
import { Chapter, StatementSequence } from 'js-slang/dist/types';
import { Node } from 'js-slang/dist/types';
import { KonvaEventObject } from 'konva/lib/Node';
import React from 'react';
Expand Down Expand Up @@ -28,14 +29,16 @@ export class ControlStack extends Visible implements IHoverable {

constructor(
/** the control object */
readonly control: Control
readonly control: Control,
readonly chapter: Chapter
) {
super();
this._x = ControlStashConfig.ControlPosX;
this._y = ControlStashConfig.ControlPosY;
this._width = ControlStashConfig.ControlItemWidth;
this._height = ControlStashConfig.StashItemHeight + ControlStashConfig.StashItemTextPadding * 2;
this.control = control;
this.chapter = chapter;

// Function to convert the stack items to their components
let i = 0;
Expand All @@ -57,7 +60,8 @@ export class ControlStack extends Visible implements IHoverable {
this._height,
i,
highlightOnHover,
unhighlightOnHover
unhighlightOnHover,
this.chapter
);
this._height += component.height();
i += 1;
Expand Down Expand Up @@ -141,6 +145,6 @@ export const isInstr = (command: ControlItem): command is Instr => {
* @param command A ControlItem
* @returns true if the ControlItem is an esNode and false if it is an instruction.
*/
export const isNode = (command: ControlItem): command is Node => {
export const isNode = (command: ControlItem): command is Node | StatementSequence => {
return (command as Node).type !== undefined;
};
8 changes: 5 additions & 3 deletions src/features/cseMachine/components/StashStack.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Stash } from 'js-slang/dist/cse-machine/interpreter';
import { Value } from 'js-slang/dist/types';
import { Chapter, Value } from 'js-slang/dist/types';
import React from 'react';

import CseMachine from '../CseMachine';
Expand All @@ -14,18 +14,20 @@ export class StashStack extends Visible {

constructor(
/** the stash object */
readonly stash: Stash
readonly stash: Stash,
readonly chapter: Chapter
) {
super();
this._x = ControlStashConfig.StashPosX;
this._y = ControlStashConfig.StashPosY;
this._width = 0;
this._height = 0;
this.chapter = chapter;

// Function to convert the stack items to their components
let i = 0;
const stashItemToComponent = (stashItem: Value) => {
const component = getStashItemComponent(stashItem, this._width, i);
const component = getStashItemComponent(stashItem, this._width, i, this.chapter);
this._width += component.width();
this._height = Math.max(this._height, component.height());
i += 1;
Expand Down
3 changes: 3 additions & 0 deletions src/features/cseMachine/components/Text.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import {
setHoveredCursor,
setUnhoveredCursor
} from '../CseMachineUtils';
import { isCustomPrimitive } from '../utils/altLangs';
import { Visible } from './Visible';

export interface TextOptions {
Expand Down Expand Up @@ -64,6 +65,8 @@ export class Text extends Visible implements IHoverable {

this.fullStr = this.partialStr = isSourceObject(data)
? data.toReplString()
: isCustomPrimitive(data)
? String(data)
: isStringIdentifiable
? JSON.stringify(data) || String(data)
: String(data);
Expand Down
Loading