From c18ec8c3f7155208733b96011199816adfc36fa2 Mon Sep 17 00:00:00 2001 From: Jeremy Wall Date: Mon, 25 May 2020 10:58:45 -0400 Subject: [PATCH] DEV: Unify package loading to one place. Also record the list of locations we need to import from. --- src/build/mod.rs | 52 +++++++++++------------------------ src/build/opcode/cache.rs | 8 +++--- src/build/opcode/pointer.rs | 6 ++-- src/build/opcode/translate.rs | 37 +++++++++++++++++-------- src/build/opcode/vm.rs | 11 ++++---- 5 files changed, 54 insertions(+), 60 deletions(-) diff --git a/src/build/mod.rs b/src/build/mod.rs index c3d56e8..8676d94 100644 --- a/src/build/mod.rs +++ b/src/build/mod.rs @@ -17,8 +17,6 @@ use std::cell::RefCell; use std::collections::HashMap; use std::convert::TryInto; use std::error::Error; -use std::fs::File; -use std::io::Read; use std::path::PathBuf; use std::process; use std::rc::Rc; @@ -32,10 +30,9 @@ use simple_error; use crate::ast::*; use crate::build::opcode::pointer::OpPointer; use crate::build::opcode::translate; -use crate::build::opcode::translate::PositionMap; +use crate::build::opcode::translate::OpsMap; use crate::build::opcode::Environment; use crate::build::opcode::VM; -use crate::error; use crate::iter::OffsetStrIter; use crate::parse::parse; @@ -147,15 +144,11 @@ where pub fn build>(&mut self, file: P) -> BuildResult { let file = file.into(); self.working_dir = file.parent().unwrap().to_path_buf(); - let mut f = self.open_file(&Position::new(0, 0, 0), &file)?; - let mut s = String::new(); - f.read_to_string(&mut s)?; - let input = OffsetStrIter::new(&s).with_src_file(file.clone()); - // TODO(jwall): Pass in the file name? - let eval_result = self.eval_input(input, Some(file.clone())); + let ptr = self.environment.borrow_mut().get_ops_for_path(&file)?; + let eval_result = self.eval_ops(ptr, Some(file.clone())); match eval_result { - Ok(v) => { - self.last = Some(v); + Ok(_) => { + self.last = self.out.clone(); Ok(()) } Err(e) => { @@ -169,19 +162,6 @@ where } } - fn open_file>(&self, pos: &Position, path: P) -> Result> { - let path = path.into(); - match File::open(&path) { - Ok(f) => Ok(f), - Err(e) => Err(error::BuildError::with_pos( - format!("Error opening file {} {}", path.to_string_lossy(), e), - error::ErrorType::TypeFail, - pos.clone(), - ) - .to_boxed()), - } - } - /// Puts the builder in validation mode. /// /// Among other things this means that assertions will be evaluated and their results @@ -190,11 +170,8 @@ where self.validate_mode = true; } - /// Builds a list of parsed UCG Statements. - pub fn eval_stmts(&mut self, ast: Vec, path: Option) -> BuildResult { - // We should probably stash this in an op_cache somewhere? - let ops = translate::AST::translate(ast, &self.working_dir); - let mut vm = VM::new(self.strict, Rc::new(ops), &self.working_dir); + fn eval_ops(&mut self, ops: OpPointer, path: Option) -> BuildResult { + let mut vm = VM::with_pointer(self.strict, ops, &self.working_dir); if path.is_some() { vm.set_path(path.unwrap()); } @@ -206,6 +183,13 @@ where Ok(()) } + /// Builds a list of parsed UCG Statements. + pub fn eval_stmts(&mut self, ast: Vec, path: Option) -> BuildResult { + // We should probably stash this in an op_cache somewhere? + let ops = translate::AST::translate(ast, &self.working_dir); + self.eval_ops(OpPointer::new(Rc::new(ops)), path) + } + pub fn repl(&mut self, mut editor: rustyline::Editor<()>, config_home: PathBuf) -> BuildResult { // loop let mut lines = crate::io::StatementAccumulator::new(); @@ -215,7 +199,7 @@ where println!(""); } // Initialize VM with an empty OpPointer - let mut vm = VM::new(self.strict, Rc::new(PositionMap::new()), &self.working_dir); + let mut vm = VM::new(self.strict, Rc::new(OpsMap::new()), &self.working_dir); loop { // print prompt let line = match editor.readline(&format!("{}> ", lines.next_line())) { @@ -296,7 +280,6 @@ where } } - // TODO(jwall): The repl is going to have to be in here. pub fn eval_input( &mut self, input: OffsetStrIter, @@ -320,10 +303,7 @@ where } pub fn eval_expr(&mut self, expr: Expression) -> Result, Box> { - let mut ops_map = translate::PositionMap { - ops: Vec::new(), - pos: Vec::new(), - }; + let mut ops_map = translate::OpsMap::new(); translate::AST::translate_stmt( Statement::Expression(expr), &mut ops_map, diff --git a/src/build/opcode/cache.rs b/src/build/opcode/cache.rs index 99d44fd..118ec7c 100644 --- a/src/build/opcode/cache.rs +++ b/src/build/opcode/cache.rs @@ -16,13 +16,13 @@ use std::collections::BTreeMap; use std::path::PathBuf; use std::rc::Rc; -use super::translate::PositionMap; +use super::translate::OpsMap; use super::Error; use super::OpPointer; /// A Cache of Op codes. pub struct Ops { - ops: BTreeMap>, + ops: BTreeMap>, } impl Ops { @@ -37,10 +37,10 @@ impl Ops { } } -pub struct Entry<'a>(btree_map::Entry<'a, PathBuf, Rc>); +pub struct Entry<'a>(btree_map::Entry<'a, PathBuf, Rc>); impl<'a> Entry<'a> { - pub fn get_pointer_or_else Result, P: Into>( + pub fn get_pointer_or_else Result, P: Into>( self, f: F, path: P, diff --git a/src/build/opcode/pointer.rs b/src/build/opcode/pointer.rs index 46f4cbf..403ce3c 100644 --- a/src/build/opcode/pointer.rs +++ b/src/build/opcode/pointer.rs @@ -16,18 +16,18 @@ use std::rc::Rc; use crate::ast::Position; -use super::translate::PositionMap; +use super::translate::OpsMap; use super::{Error, Op}; #[derive(Debug, PartialEq, Clone)] pub struct OpPointer { - pub pos_map: Rc, + pub pos_map: Rc, pub ptr: Option, pub path: Option, } impl OpPointer { - pub fn new(ops: Rc) -> Self { + pub fn new(ops: Rc) -> Self { // If we load an empty program what happens? Self { pos_map: ops, diff --git a/src/build/opcode/translate.rs b/src/build/opcode/translate.rs index 9d1be26..9a0eb9c 100644 --- a/src/build/opcode/translate.rs +++ b/src/build/opcode/translate.rs @@ -11,6 +11,7 @@ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. +use std::collections::BTreeMap; use std::path::Path; use crate::ast::{ @@ -25,19 +26,31 @@ use crate::build::opcode::{Hook, Op}; pub struct AST(); #[derive(Debug, PartialEq)] -pub struct PositionMap { +pub struct OpsMap { pub ops: Vec, pub pos: Vec, + pub links: BTreeMap, } -impl PositionMap { +impl OpsMap { pub fn new() -> Self { - PositionMap { + OpsMap { ops: Vec::new(), pos: Vec::new(), + links: BTreeMap::new(), } } + pub fn with_ops(mut self, ops: Vec, pos: Vec) -> Self { + self.ops = ops; + self.pos = pos; + self + } + + pub fn add_link(&mut self, path: String) { + self.links.insert(path, self.len() - 1); + } + pub fn len(&self) -> usize { self.ops.len() } @@ -53,13 +66,13 @@ impl PositionMap { } impl AST { - pub fn translate>(stmts: Vec, root: &P) -> PositionMap { - let mut ops = PositionMap::new(); + pub fn translate>(stmts: Vec, root: &P) -> OpsMap { + let mut ops = OpsMap::new(); Self::translate_stmts(stmts, &mut ops, root.as_ref()); return ops; } - pub fn translate_stmt(stmt: Statement, mut ops: &mut PositionMap, root: &Path) { + pub fn translate_stmt(stmt: Statement, mut ops: &mut OpsMap, root: &Path) { match stmt { Statement::Expression(expr) => { let expr_pos = expr.pos().clone(); @@ -90,13 +103,13 @@ impl AST { } } - fn translate_stmts(stmts: Vec, mut ops: &mut PositionMap, root: &Path) { + fn translate_stmts(stmts: Vec, mut ops: &mut OpsMap, root: &Path) { for stmt in stmts { Self::translate_stmt(stmt, &mut ops, root); } } - fn translate_expr(expr: Expression, mut ops: &mut PositionMap, root: &Path) { + fn translate_expr(expr: Expression, mut ops: &mut OpsMap, root: &Path) { match expr { Expression::Simple(v) => { Self::translate_value(v, &mut ops, root); @@ -428,8 +441,10 @@ impl AST { } } Expression::Import(def) => { + let link_path = def.path.fragment.clone(); ops.push(Op::Val(Primitive::Str(def.path.fragment)), def.path.pos); ops.push(Op::Runtime(Hook::Import), def.pos); + ops.add_link(link_path); } Expression::Include(def) => { ops.push(Op::Val(Primitive::Str(def.typ.fragment)), def.typ.pos); @@ -556,7 +571,7 @@ impl AST { pos: Position, part: TemplatePart, elems: &mut EI, - mut ops: &mut PositionMap, + mut ops: &mut OpsMap, place_holder: bool, root: &Path, ) { @@ -585,7 +600,7 @@ impl AST { } fn translate_copy( - mut ops: &mut PositionMap, + mut ops: &mut OpsMap, flds: Vec<(Token, Expression)>, pos: Position, root: &Path, @@ -601,7 +616,7 @@ impl AST { ops.push(Op::PopSelf, pos); } - fn translate_value(value: Value, mut ops: &mut PositionMap, root: &Path) { + fn translate_value(value: Value, mut ops: &mut OpsMap, root: &Path) { match value { Value::Int(i) => ops.push(Op::Val(Primitive::Int(i.val)), i.pos), Value::Float(f) => ops.push(Op::Val(Primitive::Float(f.val)), f.pos), diff --git a/src/build/opcode/vm.rs b/src/build/opcode/vm.rs index e372074..6b9c78c 100644 --- a/src/build/opcode/vm.rs +++ b/src/build/opcode/vm.rs @@ -23,7 +23,7 @@ use super::environment::Environment; use super::pointer::OpPointer; use super::runtime; use super::scope::Stack; -use super::translate::PositionMap; +use super::translate::OpsMap; use super::Composite::{List, Tuple}; use super::Hook; use super::Primitive::{Bool, Empty, Float, Int, Str}; @@ -55,7 +55,7 @@ pub struct VM { } impl VM { - pub fn new>(strict: bool, ops: Rc, working_dir: P) -> Self { + pub fn new>(strict: bool, ops: Rc, working_dir: P) -> Self { Self::with_pointer(strict, OpPointer::new(ops), working_dir) } @@ -394,10 +394,9 @@ impl VM { pkg_pos.clone(), pkg_pos, ]; - Some(OpPointer::new(Rc::new(PositionMap { - ops: pkg_ops, - pos: pos_list, - }))) + Some(OpPointer::new(Rc::new( + OpsMap::new().with_ops(pkg_ops, pos_list), + ))) } else { None };