Readd conflicting files

This commit is contained in:
coolreader18
2018-12-18 19:03:04 -06:00
parent dfadd03f95
commit 396842ef9d
3 changed files with 259 additions and 0 deletions

89
wasm/app/index.html Normal file
View File

@@ -0,0 +1,89 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>RustPython Demo</title>
<style type="text/css" media="screen">
textarea {
font-family: monospace;
resize: vertical;
}
#code {
height: 35vh;
width: 95vw;
}
#console {
height: 35vh;
width: 95vw;
}
#run-btn {
width: 6em;
height: 2em;
font-size: 24px;
}
#error {
color: tomato;
margin-top: 10px;
font-family: monospace;
}
</style>
</head>
<body>
<h1>RustPython Demo</h1>
<p>
RustPython is a Python interpreter writter in Rust. This demo is
compiled from Rust to WebAssembly so it runs in the browser
</p>
<p>Please input your python code below and click <kbd>Run</kbd>:</p>
<p>
Alternatively, open up your browser's devtools and play with
<code>rp.eval_py('print("a")')</code>
</p>
<textarea id="code">
n1 = 0
n2 = 1
count = 0
until = 10
print("These are the first " + str(until) + " number in a Fibonacci sequence:")
while count < until:
print(n1)
n1, n2 = n2, n1 + n2
count += 1
</textarea>
<button id="run-btn">Run &#9655;</button>
<div id="error"></div>
<script src="./bootstrap.js"></script>
<h3>Standard Output</h3>
<textarea id="console">Loading...</textarea>
<p>Here's some info regarding the <code>rp.eval_py()</code> function</p>
<ul>
<li>
You can return variables from python and get them returned to
JS, with the only requirement being that they're serializable
with <code>json.dumps</code>.
</li>
<li>
You can pass an object as the second argument to the function,
and that will be available in python as the variable
<code>js_vars</code>. Again, only values that can be serialized
with <code>JSON.stringify()</code> will go through.
</li>
</ul>
<!-- "Fork me on GitHub" banner -->
<a href="https://github.com/RustPython/RustPython"
><img
style="position: absolute; top: 0; right: 0; border: 0;"
src="https://s3.amazonaws.com/github/ribbons/forkme_right_green_007200.png"
alt="Fork me on GitHub"
/></a>
</body>
</html>

27
wasm/app/index.js Normal file
View File

@@ -0,0 +1,27 @@
import * as rp from 'rustpython_wasm';
// so people can play around with it
window.rp = rp;
function runCodeFromTextarea(_) {
const consoleElement = document.getElementById('console');
const errorElement = document.getElementById('error');
// Clean the console and errors
consoleElement.value = '';
errorElement.textContent = '';
const code = document.getElementById('code').value;
try {
rp.run_from_textbox(code);
} catch (e) {
errorElement.textContent = e;
console.error(e);
}
}
document
.getElementById('run-btn')
.addEventListener('click', runCodeFromTextarea);
runCodeFromTextarea(); // Run once for demo

143
wasm/src/lib.rs Normal file
View File

@@ -0,0 +1,143 @@
mod wasm_builtins;
extern crate js_sys;
extern crate rustpython_vm;
extern crate wasm_bindgen;
extern crate web_sys;
use rustpython_vm::compile;
use rustpython_vm::pyobject::{self, PyObjectRef, PyResult};
use rustpython_vm::VirtualMachine;
use wasm_bindgen::prelude::*;
use web_sys::console;
fn py_str_err(vm: &mut VirtualMachine, py_err: &PyObjectRef) -> String {
vm.to_pystr(&py_err)
.unwrap_or_else(|_| "Error, and error getting error message".into())
}
fn py_to_js(vm: &mut VirtualMachine, py_obj: PyObjectRef) -> JsValue {
let dumps = rustpython_vm::import::import(
vm,
std::path::PathBuf::default(),
"json",
&Some("dumps".into()),
)
.expect("Couldn't get json.dumps function");
match vm.invoke(dumps, pyobject::PyFuncArgs::new(vec![py_obj], vec![])) {
Ok(value) => {
let json = vm.to_pystr(&value).unwrap();
js_sys::JSON::parse(&json).unwrap_or(JsValue::UNDEFINED)
}
Err(_) => JsValue::UNDEFINED,
}
}
fn js_to_py(vm: &mut VirtualMachine, js_val: JsValue) -> PyObjectRef {
let json = match js_sys::JSON::stringify(&js_val) {
Ok(json) => String::from(json),
Err(_) => return vm.get_none(),
};
let loads = rustpython_vm::import::import(
vm,
std::path::PathBuf::default(),
"json",
&Some("loads".into()),
)
.expect("Couldn't get json.loads function");
let py_json = vm.new_str(json);
vm.invoke(loads, pyobject::PyFuncArgs::new(vec![py_json], vec![]))
// can safely unwrap because we know it's valid JSON
.unwrap()
}
fn eval<F>(vm: &mut VirtualMachine, source: &str, setup_scope: F) -> PyResult
where
F: Fn(&mut VirtualMachine, &PyObjectRef),
{
// HACK: if the code doesn't end with newline it crashes.
let mut source = source.to_string();
if !source.ends_with('\n') {
source.push('\n');
}
let code_obj = compile::compile(vm, &source, compile::Mode::Exec, None)?;
let builtins = vm.get_builtin_scope();
let mut vars = vm.context().new_scope(Some(builtins));
setup_scope(vm, &mut vars);
vm.run_code_obj(code_obj, vars)
}
#[wasm_bindgen]
pub fn eval_py(source: &str, js_injections: Option<js_sys::Object>) -> Result<JsValue, JsValue> {
if let Some(js_injections) = js_injections.clone() {
if !js_injections.is_object() {
return Err(js_sys::TypeError::new("The second argument must be an object").into());
}
}
let mut vm = VirtualMachine::new();
vm.ctx.set_attr(
&vm.builtins,
"print",
vm.context()
.new_rustfunc(wasm_builtins::builtin_print_console),
);
let res = eval(&mut vm, source, |vm, vars| {
let injections = if let Some(js_injections) = js_injections.clone() {
js_to_py(vm, js_injections.into())
} else {
vm.new_dict()
};
vm.ctx.set_item(vars, "js_vars", injections);
});
res.map(|value| py_to_js(&mut vm, value))
.map_err(|err| py_str_err(&mut vm, &err).into())
}
#[wasm_bindgen]
pub fn run_from_textbox(source: &str) -> Result<JsValue, JsValue> {
//add hash in here
console::log_1(&"Running RustPython".into());
console::log_1(&"Running code:".into());
console::log_1(&source.to_string().into());
let mut vm = VirtualMachine::new();
// We are monkey-patching the builtin print to use console.log
// TODO: monkey-patch sys.stdout instead, after print actually uses sys.stdout
vm.ctx.set_attr(
&vm.builtins,
"print",
vm.context().new_rustfunc(wasm_builtins::builtin_print_html),
);
match eval(&mut vm, source, |_, _| {}) {
Ok(value) => {
console::log_1(&"Execution successful".into());
match value.borrow().kind {
pyobject::PyObjectKind::None => {}
_ => {
if let Ok(text) = vm.to_pystr(&value) {
wasm_builtins::print_to_html(&text);
}
}
}
Ok(JsValue::UNDEFINED)
}
Err(err) => {
console::log_1(&"Execution failed".into());
Err(py_str_err(&mut vm, &err).into())
}
}
}