mirror of
https://github.com/zaphar/ucg.git
synced 2025-07-22 18:19:54 -04:00
DEV: Removing gratuitous use of Rc.
It was unnecessary once I better understood the ownership model and it had a significant performance cost. Removing it brought the runtime for the integration tests down from an average of 6 seconds to less than a second on my laptop.
This commit is contained in:
parent
9f787972ac
commit
c1414bdde4
@ -12,16 +12,20 @@
|
|||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
|
use std::cell::RefCell;
|
||||||
|
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
|
|
||||||
//TODO(jwall): use super::assets::MemoryCache;
|
//TODO(jwall): use super::assets::MemoryCache;
|
||||||
use super::FileBuilder;
|
use super::FileBuilder;
|
||||||
|
use crate::build::opcode::Environment;
|
||||||
|
|
||||||
fn assert_build(input: &str) {
|
fn assert_build(input: &str) {
|
||||||
let i_paths = Vec::new();
|
let i_paths = Vec::new();
|
||||||
let out_buffer: Vec<u8> = Vec::new();
|
let out_buffer: Vec<u8> = Vec::new();
|
||||||
let err_buffer: Vec<u8> = Vec::new();
|
let err_buffer: Vec<u8> = Vec::new();
|
||||||
let mut b = FileBuilder::new("<Eval>", &i_paths, out_buffer, err_buffer);
|
let env = RefCell::new(Environment::new(out_buffer, err_buffer));
|
||||||
|
let mut b = FileBuilder::new("<Eval>", &i_paths, &env);
|
||||||
b.enable_validate_mode();
|
b.enable_validate_mode();
|
||||||
b.eval_string(input).unwrap();
|
b.eval_string(input).unwrap();
|
||||||
let env = b.environment.borrow();
|
let env = b.environment.borrow();
|
||||||
@ -34,7 +38,8 @@ fn assert_build_failure(input: &str, expect: Vec<Regex>) {
|
|||||||
let i_paths = Vec::new();
|
let i_paths = Vec::new();
|
||||||
let out_buffer: Vec<u8> = Vec::new();
|
let out_buffer: Vec<u8> = Vec::new();
|
||||||
let err_buffer: Vec<u8> = Vec::new();
|
let err_buffer: Vec<u8> = Vec::new();
|
||||||
let mut b = FileBuilder::new("<Eval>", &i_paths, out_buffer, err_buffer);
|
let env = RefCell::new(Environment::new(out_buffer, err_buffer));
|
||||||
|
let mut b = FileBuilder::new("<Eval>", &i_paths, &env);
|
||||||
b.enable_validate_mode();
|
b.enable_validate_mode();
|
||||||
let err = b.eval_string(input);
|
let err = b.eval_string(input);
|
||||||
match err {
|
match err {
|
||||||
|
@ -16,7 +16,6 @@
|
|||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::convert::TryInto;
|
use std::convert::TryInto;
|
||||||
use std::env;
|
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io::Read;
|
use std::io::Read;
|
||||||
@ -91,7 +90,7 @@ where
|
|||||||
Stdout: std::io::Write + Clone,
|
Stdout: std::io::Write + Clone,
|
||||||
Stderr: std::io::Write + Clone,
|
Stderr: std::io::Write + Clone,
|
||||||
{
|
{
|
||||||
pub environment: Rc<RefCell<Environment<Stdout, Stderr>>>,
|
pub environment: &'a RefCell<Environment<Stdout, Stderr>>,
|
||||||
working_dir: PathBuf,
|
working_dir: PathBuf,
|
||||||
strict: bool,
|
strict: bool,
|
||||||
// FIXME(jwall): These need to be compiled and added to the op cache.
|
// FIXME(jwall): These need to be compiled and added to the op cache.
|
||||||
@ -112,13 +111,10 @@ where
|
|||||||
pub fn new<P: Into<PathBuf>>(
|
pub fn new<P: Into<PathBuf>>(
|
||||||
working_dir: P,
|
working_dir: P,
|
||||||
import_paths: &'a Vec<PathBuf>,
|
import_paths: &'a Vec<PathBuf>,
|
||||||
stdout: Stdout,
|
environment: &'a RefCell<Environment<Stdout, Stderr>>,
|
||||||
stderr: Stderr,
|
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let mut environment = Environment::new_with_vars(stdout, stderr, env::vars().collect());
|
|
||||||
environment.populate_stdlib();
|
|
||||||
FileBuilder {
|
FileBuilder {
|
||||||
environment: Rc::new(RefCell::new(environment)),
|
environment: environment,
|
||||||
strict: false,
|
strict: false,
|
||||||
// Our import stack is initialized with ourself.
|
// Our import stack is initialized with ourself.
|
||||||
working_dir: working_dir.into(),
|
working_dir: working_dir.into(),
|
||||||
@ -201,7 +197,6 @@ where
|
|||||||
let mut vm = VM::new(
|
let mut vm = VM::new(
|
||||||
self.strict,
|
self.strict,
|
||||||
Rc::new(ops),
|
Rc::new(ops),
|
||||||
self.environment.clone(),
|
|
||||||
&self.working_dir,
|
&self.working_dir,
|
||||||
);
|
);
|
||||||
if path.is_some() {
|
if path.is_some() {
|
||||||
@ -210,7 +205,7 @@ where
|
|||||||
if self.validate_mode {
|
if self.validate_mode {
|
||||||
vm.enable_validate_mode();
|
vm.enable_validate_mode();
|
||||||
}
|
}
|
||||||
vm.run()?;
|
vm.run(self.environment)?;
|
||||||
self.out = Some(Rc::new(vm.symbols_to_tuple(false).into()));
|
self.out = Some(Rc::new(vm.symbols_to_tuple(false).into()));
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -227,7 +222,6 @@ where
|
|||||||
let mut vm = VM::new(
|
let mut vm = VM::new(
|
||||||
self.strict,
|
self.strict,
|
||||||
Rc::new(PositionMap::new()),
|
Rc::new(PositionMap::new()),
|
||||||
self.environment.clone(),
|
|
||||||
&self.working_dir,
|
&self.working_dir,
|
||||||
);
|
);
|
||||||
loop {
|
loop {
|
||||||
@ -286,7 +280,7 @@ where
|
|||||||
let stmts = parse(OffsetStrIter::new(&stmt), None)?;
|
let stmts = parse(OffsetStrIter::new(&stmt), None)?;
|
||||||
let ops = translate::AST::translate(stmts, &self.working_dir);
|
let ops = translate::AST::translate(stmts, &self.working_dir);
|
||||||
vm = vm.to_new_pointer(OpPointer::new(Rc::new(ops)));
|
vm = vm.to_new_pointer(OpPointer::new(Rc::new(ops)));
|
||||||
match vm.run() {
|
match vm.run(self.environment) {
|
||||||
// print the result
|
// print the result
|
||||||
Err(e) => eprintln!("{}", e),
|
Err(e) => eprintln!("{}", e),
|
||||||
Ok(_) => {
|
Ok(_) => {
|
||||||
@ -346,13 +340,12 @@ where
|
|||||||
let mut vm = VM::new(
|
let mut vm = VM::new(
|
||||||
self.strict,
|
self.strict,
|
||||||
Rc::new(ops_map),
|
Rc::new(ops_map),
|
||||||
self.environment.clone(),
|
|
||||||
&self.working_dir,
|
&self.working_dir,
|
||||||
);
|
);
|
||||||
if self.validate_mode {
|
if self.validate_mode {
|
||||||
vm.enable_validate_mode();
|
vm.enable_validate_mode();
|
||||||
}
|
}
|
||||||
vm.run()?;
|
vm.run(self.environment)?;
|
||||||
if let Some((val, _)) = vm.last.clone() {
|
if let Some((val, _)) = vm.last.clone() {
|
||||||
return Ok(Rc::new(val.try_into()?));
|
return Ok(Rc::new(val.try_into()?));
|
||||||
}
|
}
|
||||||
|
@ -51,7 +51,7 @@ impl<Stdout: Write + Clone, Stderr: Write + Clone> Environment<Stdout, Stderr> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_with_vars(out: Stdout, err: Stderr, vars: BTreeMap<String, String>) -> Self {
|
pub fn new_with_vars(out: Stdout, err: Stderr, vars: BTreeMap<String, String>) -> Self {
|
||||||
Self {
|
let mut me = Self {
|
||||||
val_cache: BTreeMap::new(),
|
val_cache: BTreeMap::new(),
|
||||||
env_vars: vars,
|
env_vars: vars,
|
||||||
op_cache: cache::Ops::new(),
|
op_cache: cache::Ops::new(),
|
||||||
@ -61,7 +61,9 @@ impl<Stdout: Write + Clone, Stderr: Write + Clone> Environment<Stdout, Stderr> {
|
|||||||
stdout: out,
|
stdout: out,
|
||||||
stderr: err,
|
stderr: err,
|
||||||
out_lock: BTreeSet::new(),
|
out_lock: BTreeSet::new(),
|
||||||
}
|
};
|
||||||
|
me.populate_stdlib();
|
||||||
|
return me
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_cached_path_val(&self, path: &String) -> Option<Rc<Value>> {
|
pub fn get_cached_path_val(&self, path: &String) -> Option<Rc<Value>> {
|
||||||
@ -119,7 +121,7 @@ impl<Stdout: Write + Clone, Stderr: Write + Clone> Environment<Stdout, Stderr> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn populate_stdlib(&mut self) {
|
fn populate_stdlib(&mut self) {
|
||||||
for (p, s) in stdlib::get_libs().drain() {
|
for (p, s) in stdlib::get_libs().drain() {
|
||||||
// We unwrap the error here since we expect stdlibs to
|
// We unwrap the error here since we expect stdlibs to
|
||||||
// always compile.
|
// always compile.
|
||||||
|
@ -57,12 +57,12 @@ impl Builtins {
|
|||||||
self.validate_mode = true;
|
self.validate_mode = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn handle<P, WP, O, E>(
|
pub fn handle<'a, P, WP, O, E>(
|
||||||
&mut self,
|
&mut self,
|
||||||
path: Option<P>,
|
path: Option<P>,
|
||||||
h: Hook,
|
h: Hook,
|
||||||
stack: &mut Vec<(Rc<Value>, Position)>,
|
stack: &mut Vec<(Rc<Value>, Position)>,
|
||||||
env: Rc<RefCell<Environment<O, E>>>,
|
env: &'a RefCell<Environment<O, E>>,
|
||||||
import_stack: &mut Vec<String>,
|
import_stack: &mut Vec<String>,
|
||||||
working_dir: WP,
|
working_dir: WP,
|
||||||
pos: Position,
|
pos: Position,
|
||||||
@ -178,11 +178,11 @@ impl Builtins {
|
|||||||
Ok(contents)
|
Ok(contents)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn import<P, O, E>(
|
fn import<'a, P, O, E>(
|
||||||
&mut self,
|
&mut self,
|
||||||
base_path: P,
|
base_path: P,
|
||||||
stack: &mut Vec<(Rc<Value>, Position)>,
|
stack: &mut Vec<(Rc<Value>, Position)>,
|
||||||
env: Rc<RefCell<Environment<O, E>>>,
|
env: &'a RefCell<Environment<O, E>>,
|
||||||
import_stack: &mut Vec<String>,
|
import_stack: &mut Vec<String>,
|
||||||
pos: Position,
|
pos: Position,
|
||||||
) -> Result<(), Error>
|
) -> Result<(), Error>
|
||||||
@ -220,11 +220,10 @@ impl Builtins {
|
|||||||
let mut vm = VM::with_pointer(
|
let mut vm = VM::with_pointer(
|
||||||
self.strict,
|
self.strict,
|
||||||
op_pointer,
|
op_pointer,
|
||||||
env.clone(),
|
|
||||||
normalized.parent().unwrap(),
|
normalized.parent().unwrap(),
|
||||||
)
|
)
|
||||||
.with_import_stack(import_stack.clone());
|
.with_import_stack(import_stack.clone());
|
||||||
vm.run()?;
|
vm.run(env)?;
|
||||||
let result = Rc::new(vm.symbols_to_tuple(true));
|
let result = Rc::new(vm.symbols_to_tuple(true));
|
||||||
env.borrow_mut().update_path_val(&path, result.clone());
|
env.borrow_mut().update_path_val(&path, result.clone());
|
||||||
stack.push((result, pos));
|
stack.push((result, pos));
|
||||||
@ -238,11 +237,11 @@ impl Builtins {
|
|||||||
unreachable!();
|
unreachable!();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn include<P, O, E>(
|
fn include<'a, P, O, E>(
|
||||||
&self,
|
&self,
|
||||||
base_path: P,
|
base_path: P,
|
||||||
stack: &mut Vec<(Rc<Value>, Position)>,
|
stack: &mut Vec<(Rc<Value>, Position)>,
|
||||||
env: Rc<RefCell<Environment<O, E>>>,
|
env: &'a RefCell<Environment<O, E>>,
|
||||||
pos: Position,
|
pos: Position,
|
||||||
) -> Result<(), Error>
|
) -> Result<(), Error>
|
||||||
where
|
where
|
||||||
@ -307,10 +306,10 @@ impl Builtins {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn assert<O, E>(
|
fn assert<'a, O, E>(
|
||||||
&mut self,
|
&mut self,
|
||||||
stack: &mut Vec<(Rc<Value>, Position)>,
|
stack: &mut Vec<(Rc<Value>, Position)>,
|
||||||
env: Rc<RefCell<Environment<O, E>>>,
|
env: &'a RefCell<Environment<O, E>>,
|
||||||
) -> Result<(), Error>
|
) -> Result<(), Error>
|
||||||
where
|
where
|
||||||
O: std::io::Write + Clone,
|
O: std::io::Write + Clone,
|
||||||
@ -365,11 +364,11 @@ impl Builtins {
|
|||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
fn out<P, O, E>(
|
fn out<'a, P, O, E>(
|
||||||
&self,
|
&self,
|
||||||
path: Option<P>,
|
path: Option<P>,
|
||||||
stack: &mut Vec<(Rc<Value>, Position)>,
|
stack: &mut Vec<(Rc<Value>, Position)>,
|
||||||
env: Rc<RefCell<Environment<O, E>>>,
|
env: &'a RefCell<Environment<O, E>>,
|
||||||
pos: Position,
|
pos: Position,
|
||||||
) -> Result<(), Error>
|
) -> Result<(), Error>
|
||||||
where
|
where
|
||||||
@ -432,10 +431,10 @@ impl Builtins {
|
|||||||
unreachable!();
|
unreachable!();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn convert<O, E>(
|
fn convert<'a, O, E>(
|
||||||
&self,
|
&self,
|
||||||
stack: &mut Vec<(Rc<Value>, Position)>,
|
stack: &mut Vec<(Rc<Value>, Position)>,
|
||||||
env: Rc<RefCell<Environment<O, E>>>,
|
env: &'a RefCell<Environment<O, E>>,
|
||||||
pos: Position,
|
pos: Position,
|
||||||
) -> Result<(), Error>
|
) -> Result<(), Error>
|
||||||
where
|
where
|
||||||
@ -477,10 +476,10 @@ impl Builtins {
|
|||||||
unreachable!()
|
unreachable!()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn map<O, E>(
|
fn map<'a, O, E>(
|
||||||
&self,
|
&self,
|
||||||
stack: &mut Vec<(Rc<Value>, Position)>,
|
stack: &mut Vec<(Rc<Value>, Position)>,
|
||||||
env: Rc<RefCell<Environment<O, E>>>,
|
env: &'a RefCell<Environment<O, E>>,
|
||||||
import_stack: &Vec<String>,
|
import_stack: &Vec<String>,
|
||||||
pos: Position,
|
pos: Position,
|
||||||
) -> Result<(), Error>
|
) -> Result<(), Error>
|
||||||
@ -589,10 +588,10 @@ impl Builtins {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn filter<O, E>(
|
fn filter<'a, O, E>(
|
||||||
&self,
|
&self,
|
||||||
stack: &mut Vec<(Rc<Value>, Position)>,
|
stack: &mut Vec<(Rc<Value>, Position)>,
|
||||||
env: Rc<RefCell<Environment<O, E>>>,
|
env: &'a RefCell<Environment<O, E>>,
|
||||||
import_stack: &Vec<String>,
|
import_stack: &Vec<String>,
|
||||||
pos: Position,
|
pos: Position,
|
||||||
) -> Result<(), Error>
|
) -> Result<(), Error>
|
||||||
@ -735,10 +734,10 @@ impl Builtins {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn reduce<O, E>(
|
fn reduce<'a, O, E>(
|
||||||
&self,
|
&self,
|
||||||
stack: &mut Vec<(Rc<Value>, Position)>,
|
stack: &mut Vec<(Rc<Value>, Position)>,
|
||||||
env: Rc<RefCell<Environment<O, E>>>,
|
env: &'a RefCell<Environment<O, E>>,
|
||||||
import_stack: &Vec<String>,
|
import_stack: &Vec<String>,
|
||||||
pos: Position,
|
pos: Position,
|
||||||
) -> Result<(), Error>
|
) -> Result<(), Error>
|
||||||
@ -875,11 +874,11 @@ impl Builtins {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn trace<O, E>(
|
fn trace<'a, O, E>(
|
||||||
&mut self,
|
&mut self,
|
||||||
stack: &mut Vec<(Rc<Value>, Position)>,
|
stack: &mut Vec<(Rc<Value>, Position)>,
|
||||||
pos: Position,
|
pos: Position,
|
||||||
env: Rc<RefCell<Environment<O, E>>>,
|
env: &'a RefCell<Environment<O, E>>,
|
||||||
) -> Result<(), Error>
|
) -> Result<(), Error>
|
||||||
where
|
where
|
||||||
O: std::io::Write + Clone,
|
O: std::io::Write + Clone,
|
||||||
|
@ -42,41 +42,30 @@ fn construct_reserved_word_set() -> BTreeSet<&'static str> {
|
|||||||
words
|
words
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct VM<O, E>
|
pub struct VM {
|
||||||
where
|
|
||||||
O: std::io::Write + Clone,
|
|
||||||
E: std::io::Write + Clone,
|
|
||||||
{
|
|
||||||
working_dir: PathBuf,
|
working_dir: PathBuf,
|
||||||
stack: Vec<(Rc<Value>, Position)>,
|
stack: Vec<(Rc<Value>, Position)>,
|
||||||
symbols: Stack,
|
symbols: Stack,
|
||||||
import_stack: Vec<String>,
|
import_stack: Vec<String>,
|
||||||
runtime: runtime::Builtins,
|
runtime: runtime::Builtins,
|
||||||
ops: OpPointer,
|
ops: OpPointer,
|
||||||
pub env: Rc<RefCell<Environment<O, E>>>,
|
|
||||||
pub last: Option<(Rc<Value>, Position)>,
|
pub last: Option<(Rc<Value>, Position)>,
|
||||||
self_stack: Vec<(Rc<Value>, Position)>,
|
self_stack: Vec<(Rc<Value>, Position)>,
|
||||||
reserved_words: BTreeSet<&'static str>,
|
reserved_words: BTreeSet<&'static str>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, O, E> VM<O, E>
|
impl VM {
|
||||||
where
|
|
||||||
O: std::io::Write + Clone,
|
|
||||||
E: std::io::Write + Clone,
|
|
||||||
{
|
|
||||||
pub fn new<P: Into<PathBuf>>(
|
pub fn new<P: Into<PathBuf>>(
|
||||||
strict: bool,
|
strict: bool,
|
||||||
ops: Rc<PositionMap>,
|
ops: Rc<PositionMap>,
|
||||||
env: Rc<RefCell<Environment<O, E>>>,
|
|
||||||
working_dir: P,
|
working_dir: P,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self::with_pointer(strict, OpPointer::new(ops), env, working_dir)
|
Self::with_pointer(strict, OpPointer::new(ops), working_dir)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn with_pointer<P: Into<PathBuf>>(
|
pub fn with_pointer<P: Into<PathBuf>>(
|
||||||
strict: bool,
|
strict: bool,
|
||||||
ops: OpPointer,
|
ops: OpPointer,
|
||||||
env: Rc<RefCell<Environment<O, E>>>,
|
|
||||||
working_dir: P,
|
working_dir: P,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
@ -86,7 +75,6 @@ where
|
|||||||
import_stack: Vec::new(),
|
import_stack: Vec::new(),
|
||||||
runtime: runtime::Builtins::new(strict),
|
runtime: runtime::Builtins::new(strict),
|
||||||
ops: ops,
|
ops: ops,
|
||||||
env: env,
|
|
||||||
last: None,
|
last: None,
|
||||||
self_stack: Vec::new(),
|
self_stack: Vec::new(),
|
||||||
reserved_words: construct_reserved_word_set(),
|
reserved_words: construct_reserved_word_set(),
|
||||||
@ -119,7 +107,6 @@ where
|
|||||||
import_stack: Vec::new(),
|
import_stack: Vec::new(),
|
||||||
runtime: self.runtime.clone(),
|
runtime: self.runtime.clone(),
|
||||||
ops: self.ops.clone(),
|
ops: self.ops.clone(),
|
||||||
env: self.env.clone(),
|
|
||||||
last: None,
|
last: None,
|
||||||
self_stack: self.self_stack.clone(),
|
self_stack: self.self_stack.clone(),
|
||||||
reserved_words: self.reserved_words.clone(),
|
reserved_words: self.reserved_words.clone(),
|
||||||
@ -148,7 +135,11 @@ where
|
|||||||
self.symbols.remove_symbol(sym)
|
self.symbols.remove_symbol(sym)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn run(&mut self) -> Result<(), Error> {
|
pub fn run<'a, O, E>(&mut self, env: &'a RefCell<Environment<O, E>>) -> Result<(), Error>
|
||||||
|
where
|
||||||
|
O: std::io::Write + Clone,
|
||||||
|
E: std::io::Write + Clone,
|
||||||
|
{
|
||||||
loop {
|
loop {
|
||||||
let op = if let Some(op) = self.ops.next() {
|
let op = if let Some(op) = self.ops.next() {
|
||||||
op.clone()
|
op.clone()
|
||||||
@ -184,7 +175,7 @@ where
|
|||||||
Op::Index => self.op_index(!self.runtime.strict, pos)?,
|
Op::Index => self.op_index(!self.runtime.strict, pos)?,
|
||||||
Op::SafeIndex => self.op_index(true, pos)?,
|
Op::SafeIndex => self.op_index(true, pos)?,
|
||||||
Op::Exist => self.op_exist(pos)?,
|
Op::Exist => self.op_exist(pos)?,
|
||||||
Op::Cp => self.op_copy(pos)?,
|
Op::Cp => self.op_copy(pos, env)?,
|
||||||
//FIXME(jwall): Should this take a user provided message?
|
//FIXME(jwall): Should this take a user provided message?
|
||||||
Op::Bang => self.op_bang()?,
|
Op::Bang => self.op_bang()?,
|
||||||
Op::InitThunk(jp) => self.op_thunk(idx, jp, pos)?,
|
Op::InitThunk(jp) => self.op_thunk(idx, jp, pos)?,
|
||||||
@ -199,8 +190,8 @@ where
|
|||||||
Op::Or(jp) => self.op_or(jp, pos)?,
|
Op::Or(jp) => self.op_or(jp, pos)?,
|
||||||
Op::Module(mptr) => self.op_module(idx, mptr, pos)?,
|
Op::Module(mptr) => self.op_module(idx, mptr, pos)?,
|
||||||
Op::Func(jptr) => self.op_func(idx, jptr, pos)?,
|
Op::Func(jptr) => self.op_func(idx, jptr, pos)?,
|
||||||
Op::FCall => self.op_fcall(pos)?,
|
Op::FCall => self.op_fcall(pos, env)?,
|
||||||
Op::NewScope(jp) => self.op_new_scope(jp, self.ops.clone())?,
|
Op::NewScope(jp) => self.op_new_scope(jp, self.ops.clone(), env)?,
|
||||||
Op::Return => {
|
Op::Return => {
|
||||||
&self.stack;
|
&self.stack;
|
||||||
return Ok(());
|
return Ok(());
|
||||||
@ -209,7 +200,7 @@ where
|
|||||||
self.pop()?;
|
self.pop()?;
|
||||||
}
|
}
|
||||||
Op::Typ => self.op_typ()?,
|
Op::Typ => self.op_typ()?,
|
||||||
Op::Runtime(h) => self.op_runtime(h, pos)?,
|
Op::Runtime(h) => self.op_runtime(h, pos, env)?,
|
||||||
Op::Render => self.op_render()?,
|
Op::Render => self.op_render()?,
|
||||||
Op::PushSelf => self.op_push_self()?,
|
Op::PushSelf => self.op_push_self()?,
|
||||||
Op::PopSelf => self.op_pop_self()?,
|
Op::PopSelf => self.op_pop_self()?,
|
||||||
@ -345,7 +336,7 @@ where
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn op_select_jump(&'a mut self, jp: i32) -> Result<(), Error> {
|
fn op_select_jump(&mut self, jp: i32) -> Result<(), Error> {
|
||||||
// pop field value off
|
// pop field value off
|
||||||
let (field_name, _) = self.pop()?;
|
let (field_name, _) = self.pop()?;
|
||||||
// pop search value off
|
// pop search value off
|
||||||
@ -372,7 +363,7 @@ where
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn op_module(&'a mut self, idx: usize, jptr: i32, pos: Position) -> Result<(), Error> {
|
fn op_module(&mut self, idx: usize, jptr: i32, pos: Position) -> Result<(), Error> {
|
||||||
let (mod_val, mod_val_pos) = self.pop()?;
|
let (mod_val, mod_val_pos) = self.pop()?;
|
||||||
let (result_ptr, flds, pos_list) = match mod_val.as_ref() {
|
let (result_ptr, flds, pos_list) = match mod_val.as_ref() {
|
||||||
&C(Tuple(ref flds, ref pos_list)) => (None, flds.clone(), pos_list.clone()),
|
&C(Tuple(ref flds, ref pos_list)) => (None, flds.clone(), pos_list.clone()),
|
||||||
@ -467,20 +458,24 @@ where
|
|||||||
self.op_jump(jptr)
|
self.op_jump(jptr)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn fcall_impl(
|
pub fn fcall_impl<'a, O, E>(
|
||||||
f: &Func,
|
f: &Func,
|
||||||
strict: bool,
|
strict: bool,
|
||||||
stack: &mut Vec<(Rc<Value>, Position)>,
|
stack: &mut Vec<(Rc<Value>, Position)>,
|
||||||
env: Rc<RefCell<Environment<O, E>>>,
|
env: &'a RefCell<Environment<O, E>>,
|
||||||
import_stack: &Vec<String>,
|
import_stack: &Vec<String>,
|
||||||
) -> Result<(Rc<Value>, Position), Error> {
|
) -> Result<(Rc<Value>, Position), Error>
|
||||||
|
where
|
||||||
|
O: std::io::Write + Clone,
|
||||||
|
E: std::io::Write + Clone,
|
||||||
|
{
|
||||||
let Func {
|
let Func {
|
||||||
ref ptr,
|
ref ptr,
|
||||||
ref bindings,
|
ref bindings,
|
||||||
ref snapshot,
|
ref snapshot,
|
||||||
} = f;
|
} = f;
|
||||||
// use the captured scope snapshot for the function.
|
// use the captured scope snapshot for the function.
|
||||||
let mut vm = Self::with_pointer(strict, ptr.clone(), env, std::env::current_dir()?)
|
let mut vm = Self::with_pointer(strict, ptr.clone(), std::env::current_dir()?)
|
||||||
.to_scoped(snapshot.clone())
|
.to_scoped(snapshot.clone())
|
||||||
.with_import_stack(import_stack.clone());
|
.with_import_stack(import_stack.clone());
|
||||||
for nm in bindings.iter() {
|
for nm in bindings.iter() {
|
||||||
@ -491,25 +486,33 @@ where
|
|||||||
vm.binding_push(nm.clone(), val, false, &pos, &pos)?;
|
vm.binding_push(nm.clone(), val, false, &pos, &pos)?;
|
||||||
}
|
}
|
||||||
// proceed to the function body
|
// proceed to the function body
|
||||||
vm.run()?;
|
vm.run(env)?;
|
||||||
return vm.pop();
|
return vm.pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn op_new_scope(&mut self, jp: i32, ptr: OpPointer) -> Result<(), Error> {
|
fn op_new_scope<O, E>(&mut self, jp: i32, ptr: OpPointer, env: &RefCell<Environment<O, E>>) -> Result<(), Error>
|
||||||
|
where
|
||||||
|
O: std::io::Write + Clone,
|
||||||
|
E: std::io::Write + Clone,
|
||||||
|
{
|
||||||
let scope_snapshot = self.symbols.snapshot();
|
let scope_snapshot = self.symbols.snapshot();
|
||||||
let mut vm = self
|
let mut vm = self
|
||||||
.clean_copy()
|
.clean_copy()
|
||||||
.to_new_pointer(ptr)
|
.to_new_pointer(ptr)
|
||||||
.to_scoped(scope_snapshot)
|
.to_scoped(scope_snapshot)
|
||||||
.with_import_stack(self.import_stack.clone());
|
.with_import_stack(self.import_stack.clone());
|
||||||
vm.run()?;
|
vm.run(env)?;
|
||||||
let result = vm.pop()?;
|
let result = vm.pop()?;
|
||||||
self.push(result.0, result.1)?;
|
self.push(result.0, result.1)?;
|
||||||
self.op_jump(jp)?;
|
self.op_jump(jp)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn op_fcall(&mut self, pos: Position) -> Result<(), Error> {
|
fn op_fcall<O, E>(&mut self, pos: Position, env: &RefCell<Environment<O, E>>) -> Result<(), Error>
|
||||||
|
where
|
||||||
|
O: std::io::Write + Clone,
|
||||||
|
E: std::io::Write + Clone,
|
||||||
|
{
|
||||||
let (f, f_pos) = self.pop()?;
|
let (f, f_pos) = self.pop()?;
|
||||||
let (arg_length, _) = self.pop()?;
|
let (arg_length, _) = self.pop()?;
|
||||||
if let &F(ref f) = f.as_ref() {
|
if let &F(ref f) = f.as_ref() {
|
||||||
@ -535,7 +538,7 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
let (val, _) = decorate_call!(f_pos =>
|
let (val, _) = decorate_call!(f_pos =>
|
||||||
Self::fcall_impl(f, self.runtime.strict, &mut self.stack, self.env.clone(), &self.import_stack))?;
|
Self::fcall_impl(f, self.runtime.strict, &mut self.stack, env.clone(), &self.import_stack))?;
|
||||||
self.push(val, pos.clone())?;
|
self.push(val, pos.clone())?;
|
||||||
} else {
|
} else {
|
||||||
return Err(Error::new(format!("Not a function! {:?}", f,), pos));
|
return Err(Error::new(format!("Not a function! {:?}", f,), pos));
|
||||||
@ -888,7 +891,11 @@ where
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn op_copy(&mut self, pos: Position) -> Result<(), Error> {
|
fn op_copy<O, E>(&mut self, pos: Position, env: &RefCell<Environment<O, E>>) -> Result<(), Error>
|
||||||
|
where
|
||||||
|
O: std::io::Write + Clone,
|
||||||
|
E: std::io::Write + Clone,
|
||||||
|
{
|
||||||
// This value should always be a tuple
|
// This value should always be a tuple
|
||||||
let (override_val, val_pos) = self.pop()?;
|
let (override_val, val_pos) = self.pop()?;
|
||||||
// get target value. It should be a Module or Tuple.
|
// get target value. It should be a Module or Tuple.
|
||||||
@ -965,7 +972,7 @@ where
|
|||||||
.clean_copy()
|
.clean_copy()
|
||||||
.to_new_pointer(ptr.clone())
|
.to_new_pointer(ptr.clone())
|
||||||
.with_import_stack(self.import_stack.clone());
|
.with_import_stack(self.import_stack.clone());
|
||||||
pkg_vm.run()?;
|
pkg_vm.run(env)?;
|
||||||
let (pkg_func, val_pos) = pkg_vm.pop()?;
|
let (pkg_func, val_pos) = pkg_vm.pop()?;
|
||||||
self.merge_field_into_tuple(
|
self.merge_field_into_tuple(
|
||||||
&mut flds,
|
&mut flds,
|
||||||
@ -983,10 +990,10 @@ where
|
|||||||
.with_import_stack(self.import_stack.clone());
|
.with_import_stack(self.import_stack.clone());
|
||||||
vm.push(Rc::new(S("mod".to_owned())), pos.clone())?;
|
vm.push(Rc::new(S("mod".to_owned())), pos.clone())?;
|
||||||
vm.push(Rc::new(C(Tuple(flds, flds_pos_list))), pos.clone())?;
|
vm.push(Rc::new(C(Tuple(flds, flds_pos_list))), pos.clone())?;
|
||||||
decorate_call!(pos => vm.run())?;
|
decorate_call!(pos => vm.run(env))?;
|
||||||
if let Some(ptr) = result_ptr {
|
if let Some(ptr) = result_ptr {
|
||||||
vm.ops.jump(ptr.clone())?;
|
vm.ops.jump(ptr.clone())?;
|
||||||
vm.run()?;
|
vm.run(env)?;
|
||||||
let (result_val, result_pos) = vm.pop()?;
|
let (result_val, result_pos) = vm.pop()?;
|
||||||
self.push(result_val, result_pos)?;
|
self.push(result_val, result_pos)?;
|
||||||
} else {
|
} else {
|
||||||
@ -1005,8 +1012,8 @@ where
|
|||||||
|
|
||||||
fn merge_field_into_tuple(
|
fn merge_field_into_tuple(
|
||||||
&self,
|
&self,
|
||||||
src_fields: &'a mut Vec<(String, Rc<Value>)>,
|
src_fields: &mut Vec<(String, Rc<Value>)>,
|
||||||
pos_fields: &'a mut Vec<(Position, Position)>,
|
pos_fields: &mut Vec<(Position, Position)>,
|
||||||
name: String,
|
name: String,
|
||||||
name_pos: &Position,
|
name_pos: &Position,
|
||||||
value: Rc<Value>,
|
value: Rc<Value>,
|
||||||
@ -1069,7 +1076,7 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_binding(
|
pub fn get_binding(
|
||||||
&'a self,
|
&self,
|
||||||
name: &str,
|
name: &str,
|
||||||
pos: &Position,
|
pos: &Position,
|
||||||
) -> Result<(Rc<Value>, Position), Error> {
|
) -> Result<(Rc<Value>, Position), Error> {
|
||||||
@ -1189,12 +1196,16 @@ where
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn op_runtime(&mut self, h: Hook, pos: Position) -> Result<(), Error> {
|
fn op_runtime<O, E>(&mut self, h: Hook, pos: Position, env: &RefCell<Environment<O, E>>) -> Result<(), Error>
|
||||||
|
where
|
||||||
|
O: std::io::Write + Clone,
|
||||||
|
E: std::io::Write + Clone,
|
||||||
|
{
|
||||||
self.runtime.handle(
|
self.runtime.handle(
|
||||||
self.ops.path.as_ref(),
|
self.ops.path.as_ref(),
|
||||||
h,
|
h,
|
||||||
&mut self.stack,
|
&mut self.stack,
|
||||||
self.env.clone(),
|
env,
|
||||||
&mut self.import_stack,
|
&mut self.import_stack,
|
||||||
&self.working_dir,
|
&self.working_dir,
|
||||||
pos,
|
pos,
|
||||||
|
@ -11,11 +11,13 @@
|
|||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
use super::{FileBuilder, Val};
|
|
||||||
use crate::ast::*;
|
|
||||||
|
|
||||||
use std;
|
use std;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
use std::cell::RefCell;
|
||||||
|
|
||||||
|
use super::{FileBuilder, Val};
|
||||||
|
use crate::ast::*;
|
||||||
|
use crate::build::Environment;
|
||||||
|
|
||||||
fn test_expr_to_val<'a, O, E>(mut cases: Vec<(Expression, Val)>, mut b: FileBuilder<'a, O, E>)
|
fn test_expr_to_val<'a, O, E>(mut cases: Vec<(Expression, Val)>, mut b: FileBuilder<'a, O, E>)
|
||||||
where
|
where
|
||||||
@ -33,7 +35,8 @@ fn test_eval_div_expr_fail() {
|
|||||||
let i_paths = Vec::new();
|
let i_paths = Vec::new();
|
||||||
let out: Vec<u8> = Vec::new();
|
let out: Vec<u8> = Vec::new();
|
||||||
let err: Vec<u8> = Vec::new();
|
let err: Vec<u8> = Vec::new();
|
||||||
let b = FileBuilder::new(std::env::current_dir().unwrap(), &i_paths, out, err);
|
let env = RefCell::new(Environment::new(out, err));
|
||||||
|
let b = FileBuilder::new(std::env::current_dir().unwrap(), &i_paths, &env);
|
||||||
test_expr_to_val(
|
test_expr_to_val(
|
||||||
vec![(
|
vec![(
|
||||||
Expression::Binary(BinaryOpDef {
|
Expression::Binary(BinaryOpDef {
|
||||||
@ -60,7 +63,8 @@ fn test_eval_mul_expr_fail() {
|
|||||||
let i_paths = Vec::new();
|
let i_paths = Vec::new();
|
||||||
let out: Vec<u8> = Vec::new();
|
let out: Vec<u8> = Vec::new();
|
||||||
let err: Vec<u8> = Vec::new();
|
let err: Vec<u8> = Vec::new();
|
||||||
let b = FileBuilder::new(std::env::current_dir().unwrap(), &i_paths, out, err);
|
let env = RefCell::new(Environment::new(out, err));
|
||||||
|
let b = FileBuilder::new(std::env::current_dir().unwrap(), &i_paths, &env);
|
||||||
test_expr_to_val(
|
test_expr_to_val(
|
||||||
vec![(
|
vec![(
|
||||||
Expression::Binary(BinaryOpDef {
|
Expression::Binary(BinaryOpDef {
|
||||||
@ -87,7 +91,8 @@ fn test_eval_subtract_expr_fail() {
|
|||||||
let i_paths = Vec::new();
|
let i_paths = Vec::new();
|
||||||
let out: Vec<u8> = Vec::new();
|
let out: Vec<u8> = Vec::new();
|
||||||
let err: Vec<u8> = Vec::new();
|
let err: Vec<u8> = Vec::new();
|
||||||
let b = FileBuilder::new(std::env::current_dir().unwrap(), &i_paths, out, err);
|
let env = RefCell::new(Environment::new(out, err));
|
||||||
|
let b = FileBuilder::new(std::env::current_dir().unwrap(), &i_paths, &env);
|
||||||
test_expr_to_val(
|
test_expr_to_val(
|
||||||
vec![(
|
vec![(
|
||||||
Expression::Binary(BinaryOpDef {
|
Expression::Binary(BinaryOpDef {
|
||||||
@ -113,7 +118,8 @@ fn test_eval_add_expr_fail() {
|
|||||||
let i_paths = Vec::new();
|
let i_paths = Vec::new();
|
||||||
let out: Vec<u8> = Vec::new();
|
let out: Vec<u8> = Vec::new();
|
||||||
let err: Vec<u8> = Vec::new();
|
let err: Vec<u8> = Vec::new();
|
||||||
let b = FileBuilder::new(std::env::current_dir().unwrap(), &i_paths, out, err);
|
let env = RefCell::new(Environment::new(out, err));
|
||||||
|
let b = FileBuilder::new(std::env::current_dir().unwrap(), &i_paths, &env);
|
||||||
test_expr_to_val(
|
test_expr_to_val(
|
||||||
vec![(
|
vec![(
|
||||||
Expression::Binary(BinaryOpDef {
|
Expression::Binary(BinaryOpDef {
|
||||||
@ -141,7 +147,8 @@ fn test_expr_copy_no_such_tuple() {
|
|||||||
let i_paths = Vec::new();
|
let i_paths = Vec::new();
|
||||||
let out: Vec<u8> = Vec::new();
|
let out: Vec<u8> = Vec::new();
|
||||||
let err: Vec<u8> = Vec::new();
|
let err: Vec<u8> = Vec::new();
|
||||||
let b = FileBuilder::new(std::env::current_dir().unwrap(), &i_paths, out, err);
|
let env = RefCell::new(Environment::new(out, err));
|
||||||
|
let b = FileBuilder::new(std::env::current_dir().unwrap(), &i_paths, &env);
|
||||||
test_expr_to_val(
|
test_expr_to_val(
|
||||||
vec![(
|
vec![(
|
||||||
Expression::Copy(CopyDef {
|
Expression::Copy(CopyDef {
|
||||||
|
@ -193,9 +193,12 @@ impl Converter for ExecConverter {
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod exec_test {
|
mod exec_test {
|
||||||
|
use std::cell::RefCell;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::build::FileBuilder;
|
use crate::build::FileBuilder;
|
||||||
use crate::convert::traits::Converter;
|
use crate::convert::traits::Converter;
|
||||||
|
use crate::build::opcode::Environment;
|
||||||
|
|
||||||
use std;
|
use std;
|
||||||
use std::io::Cursor;
|
use std::io::Cursor;
|
||||||
@ -205,7 +208,8 @@ mod exec_test {
|
|||||||
let i_paths = Vec::new();
|
let i_paths = Vec::new();
|
||||||
let out: Vec<u8> = Vec::new();
|
let out: Vec<u8> = Vec::new();
|
||||||
let err: Vec<u8> = Vec::new();
|
let err: Vec<u8> = Vec::new();
|
||||||
let mut b = FileBuilder::new(std::env::current_dir().unwrap(), &i_paths, out, err);
|
let env = RefCell::new(Environment::new(out, err));
|
||||||
|
let mut b = FileBuilder::new(std::env::current_dir().unwrap(), &i_paths, &env);
|
||||||
let conv = ExecConverter::new();
|
let conv = ExecConverter::new();
|
||||||
b.eval_string(
|
b.eval_string(
|
||||||
"let script = {
|
"let script = {
|
||||||
@ -228,7 +232,8 @@ mod exec_test {
|
|||||||
let i_paths = Vec::new();
|
let i_paths = Vec::new();
|
||||||
let out: Vec<u8> = Vec::new();
|
let out: Vec<u8> = Vec::new();
|
||||||
let err: Vec<u8> = Vec::new();
|
let err: Vec<u8> = Vec::new();
|
||||||
let mut b = FileBuilder::new(std::env::current_dir().unwrap(), &i_paths, out, err);
|
let env = RefCell::new(Environment::new(out, err));
|
||||||
|
let mut b = FileBuilder::new(std::env::current_dir().unwrap(), &i_paths, &env);
|
||||||
let conv = ExecConverter::new();
|
let conv = ExecConverter::new();
|
||||||
b.eval_string(
|
b.eval_string(
|
||||||
"let script = {
|
"let script = {
|
||||||
@ -258,7 +263,8 @@ mod exec_test {
|
|||||||
let i_paths = Vec::new();
|
let i_paths = Vec::new();
|
||||||
let out: Vec<u8> = Vec::new();
|
let out: Vec<u8> = Vec::new();
|
||||||
let err: Vec<u8> = Vec::new();
|
let err: Vec<u8> = Vec::new();
|
||||||
let mut b = FileBuilder::new(std::env::current_dir().unwrap(), &i_paths, out, err);
|
let env = RefCell::new(Environment::new(out, err));
|
||||||
|
let mut b = FileBuilder::new(std::env::current_dir().unwrap(), &i_paths, &env);
|
||||||
let conv = ExecConverter::new();
|
let conv = ExecConverter::new();
|
||||||
b.eval_string(
|
b.eval_string(
|
||||||
"let script = {
|
"let script = {
|
||||||
|
67
src/main.rs
67
src/main.rs
@ -17,6 +17,7 @@ extern crate dirs;
|
|||||||
extern crate rustyline;
|
extern crate rustyline;
|
||||||
extern crate ucglib;
|
extern crate ucglib;
|
||||||
|
|
||||||
|
use std::cell::RefCell;
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
@ -26,6 +27,7 @@ use std::path::{Path, PathBuf};
|
|||||||
use std::process;
|
use std::process;
|
||||||
|
|
||||||
use ucglib::build;
|
use ucglib::build;
|
||||||
|
use ucglib::build::opcode::Environment;
|
||||||
use ucglib::convert::{ConverterRegistry, ImporterRegistry};
|
use ucglib::convert::{ConverterRegistry, ImporterRegistry};
|
||||||
use ucglib::iter::OffsetStrIter;
|
use ucglib::iter::OffsetStrIter;
|
||||||
use ucglib::parse::parse;
|
use ucglib::parse::parse;
|
||||||
@ -124,14 +126,13 @@ fn build_file<'a>(
|
|||||||
validate: bool,
|
validate: bool,
|
||||||
strict: bool,
|
strict: bool,
|
||||||
import_paths: &'a Vec<PathBuf>,
|
import_paths: &'a Vec<PathBuf>,
|
||||||
|
env: &'a RefCell<Environment<StdoutWrapper, StderrWrapper>>,
|
||||||
) -> Result<build::FileBuilder<'a, StdoutWrapper, StderrWrapper>, Box<dyn Error>> {
|
) -> Result<build::FileBuilder<'a, StdoutWrapper, StderrWrapper>, Box<dyn Error>> {
|
||||||
let mut file_path_buf = PathBuf::from(file);
|
let mut file_path_buf = PathBuf::from(file);
|
||||||
if file_path_buf.is_relative() {
|
if file_path_buf.is_relative() {
|
||||||
file_path_buf = std::env::current_dir()?.join(file_path_buf);
|
file_path_buf = std::env::current_dir()?.join(file_path_buf);
|
||||||
}
|
}
|
||||||
let out = StdoutWrapper::new();
|
let mut builder = build::FileBuilder::new(std::env::current_dir()?, import_paths, env);
|
||||||
let err = StderrWrapper::new();
|
|
||||||
let mut builder = build::FileBuilder::new(std::env::current_dir()?, import_paths, out, err);
|
|
||||||
builder.set_strict(strict);
|
builder.set_strict(strict);
|
||||||
if validate {
|
if validate {
|
||||||
builder.enable_validate_mode();
|
builder.enable_validate_mode();
|
||||||
@ -143,9 +144,14 @@ fn build_file<'a>(
|
|||||||
Ok(builder)
|
Ok(builder)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn do_validate(file: &str, strict: bool, import_paths: &Vec<PathBuf>) -> bool {
|
fn do_validate<'a>(
|
||||||
|
file: &'a str,
|
||||||
|
strict: bool,
|
||||||
|
import_paths: &'a Vec<PathBuf>,
|
||||||
|
env: &'a RefCell<Environment<StdoutWrapper, StderrWrapper>>,
|
||||||
|
) -> bool {
|
||||||
println!("Validating {}", file);
|
println!("Validating {}", file);
|
||||||
match build_file(file, true, strict, import_paths) {
|
match build_file(file, true, strict, import_paths, env) {
|
||||||
Ok(b) => {
|
Ok(b) => {
|
||||||
if b.assert_results() {
|
if b.assert_results() {
|
||||||
println!("File {} Pass\n", file);
|
println!("File {} Pass\n", file);
|
||||||
@ -162,9 +168,14 @@ fn do_validate(file: &str, strict: bool, import_paths: &Vec<PathBuf>) -> bool {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn do_compile(file: &str, strict: bool, import_paths: &Vec<PathBuf>) -> bool {
|
fn do_compile<'a>(
|
||||||
|
file: &'a str,
|
||||||
|
strict: bool,
|
||||||
|
import_paths: &'a Vec<PathBuf>,
|
||||||
|
env: &'a RefCell<Environment<StdoutWrapper, StderrWrapper>>,
|
||||||
|
) -> bool {
|
||||||
println!("Building {}", file);
|
println!("Building {}", file);
|
||||||
let builder = match build_file(file, false, strict, import_paths) {
|
let builder = match build_file(file, false, strict, import_paths, env) {
|
||||||
Ok(builder) => builder,
|
Ok(builder) => builder,
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
eprintln!("{}", err);
|
eprintln!("{}", err);
|
||||||
@ -183,6 +194,7 @@ fn visit_ucg_files(
|
|||||||
validate: bool,
|
validate: bool,
|
||||||
strict: bool,
|
strict: bool,
|
||||||
import_paths: &Vec<PathBuf>,
|
import_paths: &Vec<PathBuf>,
|
||||||
|
env: &RefCell<Environment<StdoutWrapper, StderrWrapper>>,
|
||||||
) -> Result<bool, Box<dyn Error>> {
|
) -> Result<bool, Box<dyn Error>> {
|
||||||
let our_path = String::from(path.to_string_lossy());
|
let our_path = String::from(path.to_string_lossy());
|
||||||
let mut result = true;
|
let mut result = true;
|
||||||
@ -200,35 +212,35 @@ fn visit_ucg_files(
|
|||||||
let next_path = next_item.path();
|
let next_path = next_item.path();
|
||||||
let path_as_string = String::from(next_path.to_string_lossy());
|
let path_as_string = String::from(next_path.to_string_lossy());
|
||||||
if next_path.is_dir() && recurse {
|
if next_path.is_dir() && recurse {
|
||||||
if let Err(e) = visit_ucg_files(&next_path, recurse, validate, strict, import_paths)
|
if let Err(e) = visit_ucg_files(&next_path, recurse, validate, strict, import_paths, env)
|
||||||
{
|
{
|
||||||
eprintln!("{}", e);
|
eprintln!("{}", e);
|
||||||
result = false;
|
result = false;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if validate && path_as_string.ends_with("_test.ucg") {
|
if validate && path_as_string.ends_with("_test.ucg") {
|
||||||
if !do_validate(&path_as_string, strict, import_paths) {
|
if !do_validate(&path_as_string, strict, import_paths, env) {
|
||||||
result = false;
|
result = false;
|
||||||
summary.push_str(format!("{} - FAIL\n", path_as_string).as_str())
|
summary.push_str(format!("{} - FAIL\n", path_as_string).as_str())
|
||||||
} else {
|
} else {
|
||||||
summary.push_str(format!("{} - PASS\n", path_as_string).as_str())
|
summary.push_str(format!("{} - PASS\n", path_as_string).as_str())
|
||||||
}
|
}
|
||||||
} else if !validate && path_as_string.ends_with(".ucg") {
|
} else if !validate && path_as_string.ends_with(".ucg") {
|
||||||
if !do_compile(&path_as_string, strict, import_paths) {
|
if !do_compile(&path_as_string, strict, import_paths, env) {
|
||||||
result = false;
|
result = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if validate && our_path.ends_with("_test.ucg") {
|
} else if validate && our_path.ends_with("_test.ucg") {
|
||||||
if !do_validate(&our_path, strict, import_paths) {
|
if !do_validate(&our_path, strict, import_paths, env) {
|
||||||
result = false;
|
result = false;
|
||||||
summary.push_str(format!("{} - FAIL\n", our_path).as_str());
|
summary.push_str(format!("{} - FAIL\n", our_path).as_str());
|
||||||
} else {
|
} else {
|
||||||
summary.push_str(format!("{} - PASS\n", &our_path).as_str());
|
summary.push_str(format!("{} - PASS\n", &our_path).as_str());
|
||||||
}
|
}
|
||||||
} else if !validate {
|
} else if !validate {
|
||||||
if !do_compile(&our_path, strict, import_paths) {
|
if !do_compile(&our_path, strict, import_paths, env) {
|
||||||
result = false;
|
result = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -239,13 +251,18 @@ fn visit_ucg_files(
|
|||||||
Ok(result)
|
Ok(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build_command(matches: &clap::ArgMatches, import_paths: &Vec<PathBuf>, strict: bool) {
|
fn build_command(
|
||||||
|
matches: &clap::ArgMatches,
|
||||||
|
import_paths: &Vec<PathBuf>,
|
||||||
|
strict: bool,
|
||||||
|
env: &RefCell<Environment<StdoutWrapper, StderrWrapper>>,
|
||||||
|
) {
|
||||||
let files = matches.values_of("INPUT");
|
let files = matches.values_of("INPUT");
|
||||||
let recurse = matches.is_present("recurse");
|
let recurse = matches.is_present("recurse");
|
||||||
let mut ok = true;
|
let mut ok = true;
|
||||||
if files.is_none() {
|
if files.is_none() {
|
||||||
let curr_dir = std::env::current_dir().unwrap();
|
let curr_dir = std::env::current_dir().unwrap();
|
||||||
let ok = visit_ucg_files(curr_dir.as_path(), recurse, false, strict, import_paths);
|
let ok = visit_ucg_files(curr_dir.as_path(), recurse, false, strict, import_paths, env);
|
||||||
if let Ok(false) = ok {
|
if let Ok(false) = ok {
|
||||||
process::exit(1)
|
process::exit(1)
|
||||||
}
|
}
|
||||||
@ -253,7 +270,7 @@ fn build_command(matches: &clap::ArgMatches, import_paths: &Vec<PathBuf>, strict
|
|||||||
}
|
}
|
||||||
for file in files.unwrap() {
|
for file in files.unwrap() {
|
||||||
let pb = PathBuf::from(file);
|
let pb = PathBuf::from(file);
|
||||||
if let Ok(false) = visit_ucg_files(&pb, recurse, false, strict, import_paths) {
|
if let Ok(false) = visit_ucg_files(&pb, recurse, false, strict, import_paths, env) {
|
||||||
ok = false;
|
ok = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -325,12 +342,17 @@ fn fmt_command(matches: &clap::ArgMatches) -> std::result::Result<(), Box<dyn Er
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_command(matches: &clap::ArgMatches, import_paths: &Vec<PathBuf>, strict: bool) {
|
fn test_command(
|
||||||
|
matches: &clap::ArgMatches,
|
||||||
|
import_paths: &Vec<PathBuf>,
|
||||||
|
strict: bool,
|
||||||
|
env: &RefCell<Environment<StdoutWrapper, StderrWrapper>>,
|
||||||
|
) {
|
||||||
let files = matches.values_of("INPUT");
|
let files = matches.values_of("INPUT");
|
||||||
let recurse = matches.is_present("recurse");
|
let recurse = matches.is_present("recurse");
|
||||||
if files.is_none() {
|
if files.is_none() {
|
||||||
let curr_dir = std::env::current_dir().unwrap();
|
let curr_dir = std::env::current_dir().unwrap();
|
||||||
let ok = visit_ucg_files(curr_dir.as_path(), recurse, true, strict, import_paths);
|
let ok = visit_ucg_files(curr_dir.as_path(), recurse, true, strict, import_paths, env);
|
||||||
if let Ok(false) = ok {
|
if let Ok(false) = ok {
|
||||||
process::exit(1)
|
process::exit(1)
|
||||||
}
|
}
|
||||||
@ -339,7 +361,7 @@ fn test_command(matches: &clap::ArgMatches, import_paths: &Vec<PathBuf>, strict:
|
|||||||
for file in files.unwrap() {
|
for file in files.unwrap() {
|
||||||
let pb = PathBuf::from(file);
|
let pb = PathBuf::from(file);
|
||||||
//if pb.is_dir() {
|
//if pb.is_dir() {
|
||||||
if let Ok(false) = visit_ucg_files(pb.as_path(), recurse, true, strict, import_paths) {
|
if let Ok(false) = visit_ucg_files(pb.as_path(), recurse, true, strict, import_paths, env) {
|
||||||
ok = false;
|
ok = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -426,11 +448,11 @@ fn do_repl(import_paths: &Vec<PathBuf>, strict: bool) -> std::result::Result<(),
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
let env = std::cell::RefCell::new(build::opcode::Environment::new(StdoutWrapper::new(), StderrWrapper::new()));
|
||||||
let mut builder = build::FileBuilder::new(
|
let mut builder = build::FileBuilder::new(
|
||||||
std::env::current_dir()?,
|
std::env::current_dir()?,
|
||||||
import_paths,
|
import_paths,
|
||||||
StdoutWrapper::new(),
|
&env,
|
||||||
StderrWrapper::new(),
|
|
||||||
);
|
);
|
||||||
builder.set_strict(strict);
|
builder.set_strict(strict);
|
||||||
|
|
||||||
@ -451,6 +473,7 @@ fn main() {
|
|||||||
// FIXME(jwall): Do we want these to be shared or not?
|
// FIXME(jwall): Do we want these to be shared or not?
|
||||||
let registry = ConverterRegistry::make_registry();
|
let registry = ConverterRegistry::make_registry();
|
||||||
let mut import_paths = Vec::new();
|
let mut import_paths = Vec::new();
|
||||||
|
let env = RefCell::new(Environment::new(StdoutWrapper::new(), StderrWrapper::new()));
|
||||||
if let Some(mut p) = dirs::home_dir() {
|
if let Some(mut p) = dirs::home_dir() {
|
||||||
p.push(".ucg");
|
p.push(".ucg");
|
||||||
// Attempt to create directory if it doesn't exist.
|
// Attempt to create directory if it doesn't exist.
|
||||||
@ -470,9 +493,9 @@ fn main() {
|
|||||||
true
|
true
|
||||||
};
|
};
|
||||||
if let Some(matches) = app_matches.subcommand_matches("build") {
|
if let Some(matches) = app_matches.subcommand_matches("build") {
|
||||||
build_command(matches, &import_paths, strict);
|
build_command(matches, &import_paths, strict, &env);
|
||||||
} else if let Some(matches) = app_matches.subcommand_matches("test") {
|
} else if let Some(matches) = app_matches.subcommand_matches("test") {
|
||||||
test_command(matches, &import_paths, strict);
|
test_command(matches, &import_paths, strict, &env);
|
||||||
} else if let Some(matches) = app_matches.subcommand_matches("converters") {
|
} else if let Some(matches) = app_matches.subcommand_matches("converters") {
|
||||||
converters_command(matches, ®istry)
|
converters_command(matches, ®istry)
|
||||||
} else if let Some(_) = app_matches.subcommand_matches("importers") {
|
} else if let Some(_) = app_matches.subcommand_matches("importers") {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user