Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
1 change: 1 addition & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
REACT_APP_IVLE_KEY=your_ivle_key_here
REACT_APP_VERSION=$npm_package_version
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@
/build
src/styles/*.css

# deployment
terraform*

# misc
.DS_Store
.env.local
Expand Down
8 changes: 5 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"private": true,
"name": "cadet-frontend",
"version": "0.0.0",
"version": "0.1.0",
"scripts-info": {
"format": "Format source code",
"start": "Start the Webpack development server",
Expand All @@ -10,7 +10,7 @@
"update-ui-snapshots": "Update UI test snapshots"
},
"scripts": {
"build": "build-css && build-js",
"build": "node-sass-chokidar src/ -o src/ && react-scripts-ts build",
"build-css": "node-sass-chokidar src/ -o src/",
"build-js": "react-scripts-ts build",
"coverage": "./scripts/coverage-fix.sh do && react-scripts-ts test --env=jsdom --coverage && ./scripts/coverage-fix.sh undo",
Expand Down Expand Up @@ -83,12 +83,14 @@
"@types/react-router-redux": "^5.0.13",
"@types/react-test-renderer": "^16.0.1",
"@types/redux-mock-store": "^0.0.13",
"babel-core": "6",
"babel-runtime": "^6.23.0",
"coveralls": "^3.0.1",
"enzyme": "^3.3.0",
"enzyme-adapter-react-16": "^1.1.1",
"husky": "^1.0.0-rc.6",
"prettier": "^1.12.0",
"react-scripts-ts": "^2.15.1",
"react-scripts-ts": "^2.16.0",
"react-test-renderer": "^16.3.1",
"typescript": "^2.8.1"
}
Expand Down
48 changes: 34 additions & 14 deletions src/components/Playground.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,40 @@ import { SideContentTab } from './workspace/side-content'

export type PlaygroundProps = RouteComponentProps<{}>

const Playground: React.SFC<PlaygroundProps> = props => {
return (
<HotKeys className="Playground pt-dark" keyMap={keyMap}>
<WorkspaceContainer
libQuery={parseLibrary(props)}
prgrmQuery={parsePrgrm(props)}
sideContentTabs={[playgroundIntroduction]}
/>
</HotKeys>
)
type PlaygroundState = {
isGreen: boolean
}

class Playground extends React.Component<PlaygroundProps, PlaygroundState> {
private keyMap = { goGreen: 'h u l k' }

private handlers = { goGreen: () => {} }

constructor(props: PlaygroundProps) {
super(props)
this.state = { isGreen: false }
this.handlers.goGreen = this.toggleIsGreen.bind(this)
}

public render() {
return (
<HotKeys
className={'Playground pt-dark' + (this.state.isGreen ? ' GreenScreen' : '')}
keyMap={this.keyMap}
handlers={this.handlers}
>
<WorkspaceContainer
libQuery={parseLibrary(this.props)}
prgrmQuery={parsePrgrm(this.props)}
sideContentTabs={[playgroundIntroduction]}
/>
</HotKeys>
)
}

private toggleIsGreen() {
this.setState({ isGreen: !this.state.isGreen })
}
}

const parsePrgrm = (props: PlaygroundProps) => {
Expand All @@ -35,10 +59,6 @@ const parseLibrary = (props: PlaygroundProps) => {
return sourceChapters.includes(lib) ? lib : undefined
}

const keyMap = {
goGreen: 'h u l k'
}

const SICP_SITE = 'http://www.comp.nus.edu.sg/~henz/sicp_js/'
const CHAP = '\xa7'
const playgroundIntroduction: SideContentTab = {
Expand Down
2 changes: 1 addition & 1 deletion src/components/__tests__/__snapshots__/Playground.tsx.snap
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`Playground renders correctly 1`] = `
"<HotKeys className=\\"Playground pt-dark\\" keyMap={{...}}>
"<HotKeys className=\\"Playground pt-dark\\" keyMap={{...}} handlers={{...}}>
<Connect(Workspace) libQuery={[undefined]} prgrmQuery={[undefined]} sideContentTabs={{...}} />
</HotKeys>"
`;
9 changes: 2 additions & 7 deletions src/components/workspace/index.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { decompressFromEncodedURIComponent } from 'lz-string'
import Resizable, { ResizableProps, ResizeCallback } from 're-resizable'
import * as React from 'react'
import { HotKeys } from 'react-hotkeys'

import ControlBarContainer from '../../containers/workspace/ControlBarContainer'
import EditorContainer from '../../containers/workspace/EditorContainer'
Expand Down Expand Up @@ -60,7 +59,7 @@ class Workspace extends React.Component<WorkspaceProps, {}> {
*/
public render() {
return (
<HotKeys className="workspace" handlers={handlers}>
<div className="workspace">
<ControlBarContainer {...this.props.controlBarOptions} />
<div className="row workspace-parent">
<div className="editor-divider" ref={e => (this.editorDividerDiv = e!)} />
Expand All @@ -75,7 +74,7 @@ class Workspace extends React.Component<WorkspaceProps, {}> {
<ReplContainer />
</div>
</div>
</HotKeys>
</div>
)
}

Expand Down Expand Up @@ -154,10 +153,6 @@ class Workspace extends React.Component<WorkspaceProps, {}> {
}
}

const handlers = {
goGreen: () => require('../../styles/workspace-green.css')
}

const rightResizeOnly = {
top: false,
right: true,
Expand Down
7 changes: 7 additions & 0 deletions src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,20 @@ import { ConnectedRouter } from 'react-router-redux'

import ApplicationContainer from './containers/ApplicationContainer'
import { store } from './createStore'
import { VERSION } from './utils/constants'
import { history } from './utils/history'
import registerServiceWorker from './utils/registerServiceWorker'

import './styles/index.css'

const rootContainer = document.getElementById('root') as HTMLElement
;(window as any).__REDUX_STORE__ = store // need this for slang's display
// tslint:disable-next-line
console.log(
`%c Source Academy v${VERSION}; ` +
'Please visit https://github.com/source-academy/cadet-frontend/issues to report bugs or issues.',
'font-weight: bold;'
)

render(
<Provider store={store}>
Expand Down
4 changes: 2 additions & 2 deletions src/sagas/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ import * as actionTypes from '../actions/actionTypes'
import { mockAssessmentOverviews, mockAssessments } from '../mocks/api'
import { IState } from '../reducers/states'
import { Context, interrupt, runInContext } from '../slang'
import { IVLE_KEY } from '../utils/constants'
import { showSuccessMessage, showWarningMessage } from '../utils/notification'
import { IVLE_KEY } from '../utils/secrets'

function* mainSaga() {
yield* apiFetchSaga()
Expand Down Expand Up @@ -105,7 +105,7 @@ function* workspaceSaga(): SagaIterator {

function* evalCode(code: string, context: Context) {
const { result, interrupted } = yield race({
result: call(runInContext, code, context),
result: call(runInContext, code, context, { scheduler: 'async' }),
interrupted: take(actionTypes.INTERRUPT_EXECUTION)
})
if (result) {
Expand Down
59 changes: 35 additions & 24 deletions src/slang/interpreter.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
/* tslint:disable: max-classes-per-file */
/* tslint:disable: object-literal-shorthand*/
import * as es from 'estree'
import * as constants from './constants'
import { toJS } from './interop'
Expand Down Expand Up @@ -124,31 +125,41 @@ function* getArgs(context: Context, call: es.CallExpression) {

export type Evaluator<T extends es.Node> = (node: T, context: Context) => IterableIterator<Value>

/**
* WARNING: Do not use object literal shorthands, e.g.
* {
* *Literal(node: es.Literal, ...) {...},
* *ThisExpression(node: es.ThisExpression, ..._ {...},
* ...
* }
* They do not minify well, raising uncaught syntax errors in production.
* See: https://github.com/webpack/webpack/issues/7566
*/
export const evaluators: { [nodeType: string]: Evaluator<es.Node> } = {
/** Simple Values */
*Literal(node: es.Literal, context: Context) {
Literal: function*(node: es.Literal, context: Context) {
return node.value
},
*ThisExpression(node: es.ThisExpression, context: Context) {
ThisExpression: function*(node: es.ThisExpression, context: Context) {
return context.runtime.frames[0].thisContext
},
*ArrayExpression(node: es.ArrayExpression, context: Context) {
ArrayExpression: function*(node: es.ArrayExpression, context: Context) {
const res = []
for (const n of node.elements) {
res.push(yield* evaluate(n, context))
}
return res
},
*FunctionExpression(node: es.FunctionExpression, context: Context) {
FunctionExpression: function*(node: es.FunctionExpression, context: Context) {
return new Closure(node, currentFrame(context), context)
},
*ArrowFunctionExpression(node: es.Function, context: Context) {
ArrowFunctionExpression: function*(node: es.Function, context: Context) {
return new ArrowClosure(node, currentFrame(context), context)
},
*Identifier(node: es.Identifier, context: Context) {
Identifier: function*(node: es.Identifier, context: Context) {
return getVariable(context, node.name)
},
*CallExpression(node: es.CallExpression, context: Context) {
CallExpression: function*(node: es.CallExpression, context: Context) {
const callee = yield* evaluate(node.callee, context)
const args = yield* getArgs(context, node)
let thisContext
Expand All @@ -158,7 +169,7 @@ export const evaluators: { [nodeType: string]: Evaluator<es.Node> } = {
const result = yield* apply(context, callee, args, node, thisContext)
return result
},
*NewExpression(node: es.NewExpression, context: Context) {
NewExpression: function*(node: es.NewExpression, context: Context) {
const callee = yield* evaluate(node.callee, context)
const args = []
for (const arg of node.arguments) {
Expand All @@ -174,7 +185,7 @@ export const evaluators: { [nodeType: string]: Evaluator<es.Node> } = {
}
return obj
},
*UnaryExpression(node: es.UnaryExpression, context: Context) {
UnaryExpression: function*(node: es.UnaryExpression, context: Context) {
const value = yield* evaluate(node.argument, context)

const error = rttc.checkUnaryExpression(context, node.operator, value)
Expand All @@ -191,7 +202,7 @@ export const evaluators: { [nodeType: string]: Evaluator<es.Node> } = {
return +value
}
},
*BinaryExpression(node: es.BinaryExpression, context: Context) {
BinaryExpression: function*(node: es.BinaryExpression, context: Context) {
const left = yield* evaluate(node.left, context)
const right = yield* evaluate(node.right, context)

Expand Down Expand Up @@ -241,10 +252,10 @@ export const evaluators: { [nodeType: string]: Evaluator<es.Node> } = {
}
return result
},
*ConditionalExpression(node: es.ConditionalExpression, context: Context) {
ConditionalExpression: function*(node: es.ConditionalExpression, context: Context) {
return yield* this.IfStatement(node, context)
},
*LogicalExpression(node: es.LogicalExpression, context: Context) {
LogicalExpression: function*(node: es.LogicalExpression, context: Context) {
const left = yield* evaluate(node.left, context)
let error = rttc.checkLogicalExpression(context, left, true)
if (error) {
Expand All @@ -264,20 +275,20 @@ export const evaluators: { [nodeType: string]: Evaluator<es.Node> } = {
return left
}
},
*VariableDeclaration(node: es.VariableDeclaration, context: Context) {
VariableDeclaration: function*(node: es.VariableDeclaration, context: Context) {
const declaration = node.declarations[0]
const id = declaration.id as es.Identifier
const value = yield* evaluate(declaration.init!, context)
defineVariable(context, id.name, value)
return undefined
},
*ContinueStatement(node: es.ContinueStatement, context: Context) {
ContinueStatement: function*(node: es.ContinueStatement, context: Context) {
return new ContinueValue()
},
*BreakStatement(node: es.BreakStatement, context: Context) {
BreakStatement: function*(node: es.BreakStatement, context: Context) {
return new BreakValue()
},
*ForStatement(node: es.ForStatement, context: Context) {
ForStatement: function*(node: es.ForStatement, context: Context) {
if (node.init) {
yield* evaluate(node.init, context)
}
Expand Down Expand Up @@ -305,7 +316,7 @@ export const evaluators: { [nodeType: string]: Evaluator<es.Node> } = {
}
return value
},
*MemberExpression(node: es.MemberExpression, context: Context) {
MemberExpression: function*(node: es.MemberExpression, context: Context) {
let obj = yield* evaluate(node.object, context)
if (obj instanceof Closure) {
obj = obj.fun
Expand All @@ -322,7 +333,7 @@ export const evaluators: { [nodeType: string]: Evaluator<es.Node> } = {
}
}
},
*AssignmentExpression(node: es.AssignmentExpression, context: Context) {
AssignmentExpression: function*(node: es.AssignmentExpression, context: Context) {
if (node.left.type === 'MemberExpression') {
const left = node.left
const obj = yield* evaluate(left.object, context)
Expand All @@ -342,7 +353,7 @@ export const evaluators: { [nodeType: string]: Evaluator<es.Node> } = {
setVariable(context, id.name, value)
return value
},
*FunctionDeclaration(node: es.FunctionDeclaration, context: Context) {
FunctionDeclaration: function*(node: es.FunctionDeclaration, context: Context) {
const id = node.id as es.Identifier
// tslint:disable-next-line:no-any
const closure = new Closure(node as any, currentFrame(context), context)
Expand All @@ -366,7 +377,7 @@ export const evaluators: { [nodeType: string]: Evaluator<es.Node> } = {
return undefined
}
},
*ExpressionStatement(node: es.ExpressionStatement, context: Context) {
ExpressionStatement: function*(node: es.ExpressionStatement, context: Context) {
return yield* evaluate(node.expression, context)
},
*ReturnStatement(node: es.ReturnStatement, context: Context) {
Expand All @@ -382,7 +393,7 @@ export const evaluators: { [nodeType: string]: Evaluator<es.Node> } = {
return new ReturnValue(undefined)
}
},
*WhileStatement(node: es.WhileStatement, context: Context) {
WhileStatement: function*(node: es.WhileStatement, context: Context) {
let value: any // tslint:disable-line
let test
while (
Expand All @@ -399,7 +410,7 @@ export const evaluators: { [nodeType: string]: Evaluator<es.Node> } = {
}
return value
},
*ObjectExpression(node: es.ObjectExpression, context: Context) {
ObjectExpression: function*(node: es.ObjectExpression, context: Context) {
const obj = {}
for (const prop of node.properties) {
let key
Expand All @@ -412,7 +423,7 @@ export const evaluators: { [nodeType: string]: Evaluator<es.Node> } = {
}
return obj
},
*BlockStatement(node: es.BlockStatement, context: Context) {
BlockStatement: function*(node: es.BlockStatement, context: Context) {
let result: Value
for (const statement of node.body) {
result = yield* evaluate(statement, context)
Expand All @@ -426,7 +437,7 @@ export const evaluators: { [nodeType: string]: Evaluator<es.Node> } = {
}
return result
},
*Program(node: es.BlockStatement, context: Context) {
Program: function*(node: es.BlockStatement, context: Context) {
let result: Value
for (const statement of node.body) {
result = yield* evaluate(statement, context)
Expand Down
Loading