Skip to content

Commit

Permalink
fix: simplify playground
Browse files Browse the repository at this point in the history
No more weird global static mutable variables.

Signed-off-by: Prajwal S N <[email protected]>
  • Loading branch information
snprajwal committed Dec 20, 2023
1 parent 1d75d44 commit 99eef56
Show file tree
Hide file tree
Showing 6 changed files with 90 additions and 92 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[workspace]
members = ["lost_syntax", "lost_compile", "lost_playground"]
members = ["lost_*"]
resolver = "2"

[profile.release]
Expand Down
27 changes: 27 additions & 0 deletions lost_compile/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,30 @@ pub mod error;
pub mod interpret;
pub mod stdlib;
pub mod types;

use crate::error::Exception;
use interpret::Interpreter;
use log::trace;
use lost_syntax::{lex::Lexer, parse::Parser};

pub fn run(source: &str, interpreter: &mut Interpreter) -> Result<(), Vec<Exception>> {
let lexer = Lexer::new(source);
trace!("Lexing {source}");
let tokens = lexer.lex_all_sanitised().map_err(|e| {
e.into_iter()
.map(Exception::Error)
.collect::<Vec<Exception>>()
})?;
trace!("Parsing {tokens:#?}");
let parser = Parser::new(&tokens);
let root = parser.parse_all().map_err(|e| {
e.into_iter()
.map(Exception::Error)
.collect::<Vec<Exception>>()
})?;
trace!("Interpreting {root:#?}");
match interpreter.interpret_all(root.items) {
Ok(()) => Ok(()),
Err(e) => Err(vec![e]),
}
}
25 changes: 1 addition & 24 deletions lost_compile/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
#[macro_use]
extern crate log;

use lost_compile::{error::Exception, interpret::Interpreter};
use lost_syntax::{lex::Lexer, parse::Parser};
use lost_compile::{interpret::Interpreter, run};
use std::{
env, fs,
io::{self, Write},
Expand Down Expand Up @@ -62,25 +61,3 @@ fn run_repl() {
}
}
}

fn run(source: &str, interpreter: &mut Interpreter) -> Result<(), Vec<Exception>> {
let lexer = Lexer::new(source);
trace!("Lexing {source}");
let tokens = lexer.lex_all_sanitised().map_err(|e| {
e.into_iter()
.map(Exception::Error)
.collect::<Vec<Exception>>()
})?;
trace!("Parsing {tokens:#?}");
let parser = Parser::new(&tokens);
let root = parser.parse_all().map_err(|e| {
e.into_iter()
.map(Exception::Error)
.collect::<Vec<Exception>>()
})?;
trace!("Interpreting {root:#?}");
match interpreter.interpret_all(root.items) {
Ok(()) => Ok(()),
Err(e) => Err(vec![e]),
}
}
1 change: 0 additions & 1 deletion lost_playground/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,3 @@ console_error_panic_hook = { version = "0.1.6", optional = true }
wee_alloc = { version = "0.4.5", optional = true }
lost_compile = { path = "../lost_compile" }
lost_syntax = { path = "../lost_syntax" }
once_cell = "1.17.1"
124 changes: 59 additions & 65 deletions lost_playground/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,13 @@
use std::{env, sync::Mutex};

use lost_compile::{
environment::Env,
error::Exception,
interpret::Interpreter,
run,
types::{
self,
Type::{self, NativeFunc},
},
};
use lost_syntax::{lex::Lexer, parse::Parser};
use once_cell::sync::Lazy;
use std::env;
use wasm_bindgen::prelude::*;

#[cfg(feature = "wee_alloc")]
Expand All @@ -23,86 +20,83 @@ pub fn init() -> String {
console_error_panic_hook::set_once();

format!(
"Lost REPL v{} on {} ({}), Copyright (c) {}",
"Lost v{} on {} ({}), Copyright (c) {}",
env!("CARGO_PKG_VERSION"),
env::consts::OS,
env::consts::ARCH,
env!("CARGO_PKG_AUTHORS"),
)
}

struct World {
env: Env,
output: String,
#[wasm_bindgen]
#[derive(Default)]
pub struct World {
interpreter: Interpreter,
}

static WORLD: Lazy<Mutex<World>> = Lazy::new(|| {
let mut env = Env::default();
init_io(&mut env);
Mutex::new(World {
env,
output: String::default(),
})
});
const REPL_OUTPUT_VAR: &str = "REPL_OUTPUT";

#[wasm_bindgen]
impl World {
#[wasm_bindgen(constructor)]
pub fn new() -> Self {
let world = Self::default();
let mut env = Env::default();
// Initialise output variable. This is a hack
// to print to JS since stdout itself can't be
// captured and piped into a JS value.
env.set(REPL_OUTPUT_VAR.to_string(), Type::Str(String::default()));
// Add stdlib functions
init_io(&mut env);
world.interpreter.env.replace(env);
world
}

pub fn run(&mut self, src: &str) -> Result<String, String> {
clear_output(&self.interpreter);
match run(src, &mut self.interpreter) {
Ok(()) => Ok(self
.interpreter
.env
.borrow()
.get(REPL_OUTPUT_VAR.to_string())
.unwrap()
.to_string()),
Err(errors) => Err(errors
.into_iter()
.fold(String::default(), |a, b| a + &b.to_string() + "\n")
.trim()
.to_string()),
}
}
}

// Override the default init_io from stdlib
// since `println!` cannot be used with wasm
fn clear_output(interpreter: &Interpreter) {
interpreter
.env
.borrow_mut()
.assign(REPL_OUTPUT_VAR.to_string(), Type::Str(String::default()))
.expect("no output variable present");
}

/// Override the default init_io from stdlib
/// since `println!` cannot be used with wasm
fn init_io(env: &mut Env) {
// print(args)
env.set(
"print".to_string(),
NativeFunc(types::NativeFunc {
name: "print".to_string(),
args: vec!["arg".to_string()],
body: |_, args| {
body: |interpreter, args| {
let arg = args.first().expect("argument not present");
WORLD.lock().unwrap().output.push_str(&arg.to_string());
interpreter
.env
.borrow_mut()
.assign(REPL_OUTPUT_VAR.to_string(), Type::Str(arg.to_string()))
.expect("no output variable present");
Ok(Type::Number(arg.to_string().len() as f64))
},
}),
);
}

#[wasm_bindgen]
pub fn run_repl(line: &str) -> Result<String, String> {
let mut code = String::default();
let mut world = WORLD.lock().unwrap();
let env = world.env.to_owned();
// Clear the output buffer
world.output = String::default();
// Unlock the mutex since we've cloned the value
drop(world);
match run(&line, env) {
Ok(new_env) => {
code.push_str(&line);
let mut world = WORLD.lock().unwrap();
world.env = new_env;
Ok(world.output.to_owned())
}
Err(errors) => Err(errors
.into_iter()
.fold(String::default(), |a, b| a + &b.to_string() + "\n")
.trim()
.to_string()),
}
}

fn run(source: &str, env: Env) -> Result<Env, Vec<Exception>> {
let lexer = Lexer::new(source);
let tokens = lexer.lex_all_sanitised().map_err(|e| {
e.into_iter()
.map(Exception::Error)
.collect::<Vec<Exception>>()
})?;
let parser = Parser::new(&tokens);
let root = parser.parse_all().map_err(|e| {
e.into_iter()
.map(Exception::Error)
.collect::<Vec<Exception>>()
})?;
let mut interpreter = Interpreter::new(Some(env));
match interpreter.interpret_all(root.items) {
Ok(()) => Ok(interpreter.env),
Err(e) => Err(vec![e]),
}
}
3 changes: 2 additions & 1 deletion www/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ const repl = {
// Initialise
// ----------------------------------------------------------------------------

const world = new wasm.World();
repl.elemSourceInput.addEventListener("change", onInputChange);
repl.elemSourceInput.addEventListener("keyup", onInputKeyup);
repl.elemHistory.querySelector("#loading-message").remove();
Expand Down Expand Up @@ -105,7 +106,7 @@ async function processInputQueue() {
let ok = true;
if (inputText) {
try {
outputText = wasm.run_repl(inputText);
outputText = world.run(inputText);
} catch (e) {
outputText = `${e}`;
ok = false;
Expand Down

0 comments on commit 99eef56

Please sign in to comment.