Skip to content

Commit

Permalink
Add print & REPL functionality to CLI (#267)
Browse files Browse the repository at this point in the history
* Add basic REPL functionality
* Add utility function to Realm
* Rework flow to allow files to be loaded as well as open a shell
* Remove shell option (not needed now its the default)
* Update README.md & docs/debugging.md
  • Loading branch information
JohnDoneth authored Mar 8, 2020
1 parent f628f4c commit d92da39
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 14 deletions.
14 changes: 14 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,20 @@ see [CHANGELOG](./CHANGELOG.md)
- Run with `cargo run -- test.js` where `test.js` is an existing JS file
- If any JS doesn't work then it's a bug. Please raise an issue!

## Command-line Options

```
USAGE:
boa_cli [FILE]...
FLAGS:
-h, --help Prints help information
-V, --version Prints version information
ARGS:
<FILE>... The JavaScript file(s) to be evaluated
```

## Communication

Feel free to contact us on Discord https://discord.gg/tUFFk9Y
Expand Down
14 changes: 12 additions & 2 deletions boa/src/realm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@
//!A realm is represented in this implementation as a Realm struct with the fields specified from the spec
use crate::{
builtins::{
array, boolean, console, function, json, math, number, object, regexp, string, symbol,
value::{Value, ValueData},
array, boolean, console, function,
function::NativeFunctionData,
json, math, number, object, regexp, string, symbol,
value::{ToValue, Value, ValueData},
},
environment::{
declarative_environment_record::DeclarativeEnvironmentRecord,
Expand Down Expand Up @@ -65,6 +67,14 @@ impl Realm {
global.set_field_slice("Symbol", symbol::create_constructor(global));
global.set_field_slice("console", console::create_constructor(global));
}

/// Utility to add a function to the global object
pub fn register_global_func(self, func_name: &str, func: NativeFunctionData) -> Self {
self.global_obj
.set_field(func_name.to_value(), func.to_value());

self
}
}

// Similar to new_global_environment in lexical_environment, except we need to return a GlobalEnvirionment
Expand Down
29 changes: 20 additions & 9 deletions boa_cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,29 +2,27 @@
#![warn(clippy::perf)]
#![allow(clippy::cognitive_complexity)]

use boa::builtins::console::log;
use boa::{exec::Executor, forward_val, realm::Realm};
use std::io;
use std::{fs::read_to_string, path::PathBuf};
use structopt::StructOpt;

/// CLI configuration for Boa.
#[derive(Debug, StructOpt)]
#[structopt(author, about)]
struct Opt {
/// The javascript file to be evaluated.
#[structopt(name = "FILE", parse(from_os_str), default_value = "tests/js/test.js")]
/// The JavaScript file(s) to be evaluated.
#[structopt(name = "FILE", parse(from_os_str))]
files: Vec<PathBuf>,
/// Open a boa shell (WIP).
#[structopt(short, long)]
shell: bool,
}

pub fn main() -> Result<(), std::io::Error> {
let args = Opt::from_args();

let realm = Realm::create();
let realm = Realm::create().register_global_func("print", log);

let mut engine = Executor::new(realm);

for file in args.files {
for file in &args.files {
let buffer = read_to_string(file)?;

match forward_val(&mut engine, &buffer) {
Expand All @@ -33,5 +31,18 @@ pub fn main() -> Result<(), std::io::Error> {
}
}

if args.files.is_empty() {
loop {
let mut buffer = String::new();

io::stdin().read_line(&mut buffer)?;

match forward_val(&mut engine, buffer.trim_end()) {
Ok(v) => println!("{}", v.to_string()),
Err(v) => eprintln!("{}", v.to_string()),
}
}
}

Ok(())
}
7 changes: 4 additions & 3 deletions docs/debugging.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
# Debugging

There are multiple ways to debug what Boa is doing. Or maybe you just want to know how it works under the hood. Or even test some javaScript.
There are multiple ways to debug what Boa is doing. Or maybe you just want to know how it works under the hood. Or even test some JavaScript.

The first thing i usually do is add some JS [here](../tests/js/test.js).
This file will be read if no arguments are provided. Then boa will begin to parse and execute that JS.
One way to do so is to create a file in the root of the repository. For example `test.js`. Then execute `cargo run -- test.js` to run the file with boa.

You can also run boa interactively by simply calling `cargo run` without any arguments to start a shell to execute JS.

These are added in order of how the code is read:

Expand Down

0 comments on commit d92da39

Please sign in to comment.