Skip to content

Mapping Python print to JavaScript console.log #203

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 1 commit into from
Dec 3, 2018
Merged

Conversation

shinglyu
Copy link
Contributor

@rmliddle @windelbouwman would you mind reviewing this code?

I'm not sure what's the best way to allow different version of print builtin function. I add the builtins argument to VM's new(), so we can inject different version of builtin implementation to it. But maybe I need to use builder pattern or a Trait for that. What your thoughts on this?

selection_113
This is how it works, we can build more interesting webpage demo on top of it.

@windelbouwman
Copy link
Contributor

I think creating a seperate print method is not really the way to go here. It would be better to extend the existing print method to take a file= keyword argument which can then be overridden. What really should be done to reroute the standard output is implement sys.output so that this stream can be overridden in javascript.

Also, if you wish to replace the default print function with a new one, you can do so by setting the print argument on the builtin module. At least, this should be possible to do. For this you could use maybe something like vm.builtins.set_attr('print', new_js_print_func).

So far my opinions!

/// Build the builtin module,
///
/// * ctx: The Python Context
/// * builtin_overrides: A HashMap that contains (builtin item name, PyObjectRef to that item),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of overrides, try to use the set_attr method to update a builtin function.

wasm/src/lib.rs Outdated
let mut overrides = HashMap::new();
overrides.insert(String::from("print"), ctx.new_rustfunc(wasm_builtins::builtin_print));
let builtins = builtins::make_module(&ctx, overrides);
let mut vm = VirtualMachine::new(ctx, builtins);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use below here:

builtins.set_attr("print", ctx.new_rustfunc(wasm_builtins::builtin_print));

@shinglyu
Copy link
Contributor Author

Yes, your suggestion makes more sense. I'll work on it.

@shinglyu
Copy link
Contributor Author

@windelbouwman if we add a file= argument to the print function, what do you think is a good place to specify that dependency? We might have to expose that argument all the way to VirtualMachine::new(). Maybe I should add the argument as file: Option<?> and impl Default for it, so we default to None, which will use the system stdout?

@windelbouwman
Copy link
Contributor

windelbouwman commented Nov 23, 2018

Btw, the following would be best in my opinion:

let builtins = vm.import("builtins")?;
builtins.set_attr("print", ctx.new_rustfunc(javascript_print));

This will work, since modules are cached once imported, so no copy of the namespace is made. So each piece of code using the builtin module refers to the same module.

Then we do not need dependency injection into the vm during creation, and the VirtualMachine remains trivial to create!

@windelbouwman
Copy link
Contributor

If you see this python documentation: file:///usr/share/doc/python/html/library/functions.html#print

Notice that file has a default argument. Default arguments are already supported in rustpython, you can query for keyword arguments in rust code. Best way would be to leave the original print function, and implement sys.stdout instead and patch that with a sys_module.set_attr("stdout", some_object) call in rust.

@shinglyu
Copy link
Contributor Author

Ah I didn't notice that print uses sys.stdout internally! OK, I'll use sys_module.set_attr("stdout", some_object)

@windelbouwman
Copy link
Contributor

That is correct, since print does not yet use sys.stdout. It should though, in future, so the print function should not be the one to monkey patch. You can for now monkey patch the builtin print with set_attr. Later, this should be changed to patch sys.stdout in the same manner.

wasm/src/lib.rs Outdated
//let ctx = vm.context();
//let current_path = PathBuf::from(".");
//let builtins = import_module(&mut vm, current_path, "builtins").unwrap();
builtins.set_attr("print", vm.context().new_rustfunc(wasm_builtins::builtin_print));
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@windelbouwman could you kindly help me check this part? It compiles correctly but seems to panic in runtime.

The browser gives this error:

bootstrap.js:5 Error importing `index.js`: RuntimeError: unreachable
    at __rust_start_panic (wasm-function[3157]:1)
    at rust_panic (wasm-function[3135]:31)
    at std::panicking::rust_panic_with_hook::ha9514ccd859407a0 (wasm-function[3130]:305)
    at std::panicking::continue_panic_fmt::hbdf64f9b91d66da7 (wasm-function[3129]:120)
    at std::panicking::begin_panic_fmt::hb1f86670af92c2cf (wasm-function[3067]:95)
    at _$LT$alloc..rc..Rc$LT$core..cell..RefCell$LT$rustpython_vm..pyobject..PyObject$GT$$GT$$u20$as$u20$rustpython_vm..pyobject..AttributeProtocol$GT$::set_attr::h29a4da0736316e29 (wasm-function[587]:367)
    at rustpython_wasm::run_code::h6cdd6ee5f53d3532 (wasm-function[5]:344)
    at run_code (wasm-function[6]:16)
    at Module.run_code (webpack:///../pkg/rustpython_wasm.js?:34:76)
    at eval (webpack:///./index.js?:5:57)

@shinglyu
Copy link
Contributor Author

@windelbouwman I've pushed a few more commits to fix it. Please kindly review the final diff and I'll squash the commits before merge.

@shinglyu shinglyu merged commit 5734fc2 into master Dec 3, 2018
@windelbouwman windelbouwman deleted the consolelog branch February 15, 2019 16:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants