mirror of
https://github.com/RustPython/RustPython.git
synced 2026-06-02 19:39:49 +09:00
Readd conflicting files
This commit is contained in:
89
wasm/app/index.html
Normal file
89
wasm/app/index.html
Normal 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 ▷</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
27
wasm/app/index.js
Normal 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
143
wasm/src/lib.rs
Normal 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())
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user