playground: add ability to run code
This commit is contained in:
43
playground/samples/Hello.newt
Normal file
43
playground/samples/Hello.newt
Normal file
@@ -0,0 +1,43 @@
|
||||
module Main
|
||||
|
||||
-- Monad
|
||||
|
||||
class Monad (m : U → U) where
|
||||
bind : {a b} → m a → (a → m b) → m b
|
||||
pure : {a} → a → m a
|
||||
|
||||
infixl 1 _>>=_ _>>_
|
||||
_>>=_ : {m} {{Monad m}} {a b} -> (m a) -> (a -> m b) -> m b
|
||||
ma >>= amb = bind ma amb
|
||||
|
||||
_>>_ : {m} {{Monad m}} {a b} -> m a -> m b -> m b
|
||||
ma >> mb = mb
|
||||
|
||||
-- I don't want to use an empty type because it would be a proof of void
|
||||
ptype World
|
||||
|
||||
data IORes : U -> U where
|
||||
MkIORes : {a : U} -> a -> World -> IORes a
|
||||
|
||||
IO : U -> U
|
||||
IO a = World -> IORes a
|
||||
|
||||
|
||||
data Unit : U where
|
||||
MkUnit : Unit
|
||||
|
||||
|
||||
instance Monad IO where
|
||||
bind ma mab = \ w => case ma w of
|
||||
MkIORes a w => mab a w
|
||||
pure a = \ w => MkIORes a w
|
||||
|
||||
ptype String
|
||||
pfunc putStrLn : String -> IO Unit := "(s) => (w) => {
|
||||
console.log(s)
|
||||
return MkIORes(Unit,MkUnit,w)
|
||||
}"
|
||||
|
||||
main : IO Unit
|
||||
main = do
|
||||
putStrLn "hello, world"
|
||||
29
playground/samples/frame.html
Normal file
29
playground/samples/frame.html
Normal file
@@ -0,0 +1,29 @@
|
||||
<html>
|
||||
<head>
|
||||
<script>
|
||||
realLog = console.log
|
||||
messages = []
|
||||
console.log = (...args) => {
|
||||
messages.push(args.join(' '))
|
||||
realLog(...args)
|
||||
}
|
||||
window.addEventListener('message', (ev) => {
|
||||
realLog('got', ev)
|
||||
let {cmd, src} = ev.data
|
||||
if (cmd === 'exec') {
|
||||
try {
|
||||
eval(src)
|
||||
} catch (e) {
|
||||
console.log(e)
|
||||
}
|
||||
}
|
||||
window.parent.postMessage({messages}, '*')
|
||||
messages = []
|
||||
})
|
||||
realLog('IFRAME INITIALIZED')
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -10,11 +10,31 @@ monaco.languages.setMonarchTokensProvider("newt", newtTokens);
|
||||
monaco.languages.setLanguageConfiguration("newt", newtConfig);
|
||||
|
||||
const newtWorker = new Worker("worker.js"); //new URL("worker.js", import.meta.url))
|
||||
const iframe = document.createElement("iframe");
|
||||
iframe.src = "frame.html";
|
||||
iframe.style.display = "none";
|
||||
document.body.appendChild(iframe);
|
||||
|
||||
function run(src: string) {
|
||||
newtWorker.postMessage({ src });
|
||||
}
|
||||
|
||||
function runOutput() {
|
||||
const src = state.javascript.value
|
||||
console.log("RUN", iframe.contentWindow);
|
||||
try {
|
||||
iframe.contentWindow?.postMessage({ cmd: "exec", src }, "*");
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
}
|
||||
|
||||
window.onmessage = (ev) => {
|
||||
console.log("window got", ev.data);
|
||||
if (ev.data.messages)
|
||||
state.messages.value = ev.data.messages;
|
||||
};
|
||||
|
||||
newtWorker.onmessage = (ev) => {
|
||||
state.output.value = ev.data.output;
|
||||
state.javascript.value = ev.data.javascript;
|
||||
@@ -30,6 +50,7 @@ self.MonacoEnvironment = {
|
||||
const state = {
|
||||
output: signal(""),
|
||||
javascript: signal(""),
|
||||
messages: signal<string[]>([]),
|
||||
editor: signal<monaco.editor.IStandaloneCodeEditor | null>(null),
|
||||
};
|
||||
|
||||
@@ -110,19 +131,35 @@ function Result() {
|
||||
return h("div", { id: "result" }, text);
|
||||
}
|
||||
|
||||
function Console() {
|
||||
const messages = state.messages.value ?? []
|
||||
return h(
|
||||
"div",
|
||||
{ id: "console" },
|
||||
messages.map((msg) => h("div", { className: "message" }, msg))
|
||||
);
|
||||
}
|
||||
|
||||
const RESULTS = "Output";
|
||||
const JAVASCRIPT = "JS";
|
||||
const CONSOLE = "Console";
|
||||
|
||||
function Tabs() {
|
||||
const [selected, setSelected] = useState(RESULTS);
|
||||
|
||||
const [selected, setSelected] = useState(localStorage.tab ?? RESULTS);
|
||||
const Tab = (label: string) => {
|
||||
let onClick = () => setSelected(label);
|
||||
let onClick = () => {
|
||||
setSelected(label);
|
||||
localStorage.tab = label
|
||||
}
|
||||
let className = "tab";
|
||||
if (label == selected) className += " selected";
|
||||
return h("div", { className, onClick }, label);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (state.messages.value) setSelected(CONSOLE)
|
||||
}, [state.messages.value])
|
||||
|
||||
let body;
|
||||
switch (selected) {
|
||||
case RESULTS:
|
||||
@@ -131,6 +168,9 @@ function Tabs() {
|
||||
case JAVASCRIPT:
|
||||
body = h(JavaScript, {});
|
||||
break;
|
||||
case CONSOLE:
|
||||
body = h(Console, {});
|
||||
break;
|
||||
default:
|
||||
body = h("div", {});
|
||||
}
|
||||
@@ -138,13 +178,14 @@ function Tabs() {
|
||||
return h(
|
||||
"div",
|
||||
{ className: "tabPanel right" },
|
||||
h("div", { className: "tabBar" }, Tab(RESULTS), Tab(JAVASCRIPT)),
|
||||
h("div", { className: "tabBar" }, Tab(RESULTS), Tab(JAVASCRIPT), Tab(CONSOLE)),
|
||||
h("div", { className: "tabBody" }, body)
|
||||
);
|
||||
}
|
||||
|
||||
const SAMPLES = [
|
||||
"Tour.newt",
|
||||
"Hello.newt",
|
||||
"DSL.newt",
|
||||
"Tree.newt",
|
||||
"Reasoning.newt",
|
||||
@@ -180,12 +221,18 @@ function EditWrap({vertical, toggle}: {vertical: boolean, toggle: () => void}) {
|
||||
h("option", { value: "" }, "choose sample"),
|
||||
options
|
||||
),
|
||||
h('div', {style: {flex: '1 1'}}),
|
||||
h('button', {onClick: toggle},
|
||||
h('svg', {width:20, height: 20},
|
||||
h('path',{d,fill:'none',stroke:'black'})
|
||||
)
|
||||
h("div", { style: { flex: "1 1" } }),
|
||||
h("button", { onClick: runOutput
|
||||
}, "⏵"),
|
||||
h(
|
||||
"button",
|
||||
{ onClick: toggle },
|
||||
h(
|
||||
"svg",
|
||||
{ width: 20, height: 20 },
|
||||
h("path", { d, fill: "none", stroke: "black" })
|
||||
)
|
||||
)
|
||||
),
|
||||
h("div", { className: "tabBody" }, h(Editor, { initialValue: value }))
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user