DEV: Unify package loading to one place.

Also record the list of locations we need to import from.
This commit is contained in:
Jeremy Wall 2020-05-25 10:58:45 -04:00
parent 8a9ee59234
commit c18ec8c3f7
5 changed files with 54 additions and 60 deletions

View File

@ -17,8 +17,6 @@ use std::cell::RefCell;
use std::collections::HashMap; use std::collections::HashMap;
use std::convert::TryInto; use std::convert::TryInto;
use std::error::Error; use std::error::Error;
use std::fs::File;
use std::io::Read;
use std::path::PathBuf; use std::path::PathBuf;
use std::process; use std::process;
use std::rc::Rc; use std::rc::Rc;
@ -32,10 +30,9 @@ use simple_error;
use crate::ast::*; use crate::ast::*;
use crate::build::opcode::pointer::OpPointer; use crate::build::opcode::pointer::OpPointer;
use crate::build::opcode::translate; 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::Environment;
use crate::build::opcode::VM; use crate::build::opcode::VM;
use crate::error;
use crate::iter::OffsetStrIter; use crate::iter::OffsetStrIter;
use crate::parse::parse; use crate::parse::parse;
@ -147,15 +144,11 @@ where
pub fn build<P: Into<PathBuf>>(&mut self, file: P) -> BuildResult { pub fn build<P: Into<PathBuf>>(&mut self, file: P) -> BuildResult {
let file = file.into(); let file = file.into();
self.working_dir = file.parent().unwrap().to_path_buf(); self.working_dir = file.parent().unwrap().to_path_buf();
let mut f = self.open_file(&Position::new(0, 0, 0), &file)?; let ptr = self.environment.borrow_mut().get_ops_for_path(&file)?;
let mut s = String::new(); let eval_result = self.eval_ops(ptr, Some(file.clone()));
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()));
match eval_result { match eval_result {
Ok(v) => { Ok(_) => {
self.last = Some(v); self.last = self.out.clone();
Ok(()) Ok(())
} }
Err(e) => { Err(e) => {
@ -169,19 +162,6 @@ where
} }
} }
fn open_file<P: Into<PathBuf>>(&self, pos: &Position, path: P) -> Result<File, Box<dyn Error>> {
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. /// Puts the builder in validation mode.
/// ///
/// Among other things this means that assertions will be evaluated and their results /// Among other things this means that assertions will be evaluated and their results
@ -190,11 +170,8 @@ where
self.validate_mode = true; self.validate_mode = true;
} }
/// Builds a list of parsed UCG Statements. fn eval_ops(&mut self, ops: OpPointer, path: Option<PathBuf>) -> BuildResult {
pub fn eval_stmts(&mut self, ast: Vec<Statement>, path: Option<PathBuf>) -> BuildResult { let mut vm = VM::with_pointer(self.strict, ops, &self.working_dir);
// 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);
if path.is_some() { if path.is_some() {
vm.set_path(path.unwrap()); vm.set_path(path.unwrap());
} }
@ -206,6 +183,13 @@ where
Ok(()) Ok(())
} }
/// Builds a list of parsed UCG Statements.
pub fn eval_stmts(&mut self, ast: Vec<Statement>, path: Option<PathBuf>) -> 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 { pub fn repl(&mut self, mut editor: rustyline::Editor<()>, config_home: PathBuf) -> BuildResult {
// loop // loop
let mut lines = crate::io::StatementAccumulator::new(); let mut lines = crate::io::StatementAccumulator::new();
@ -215,7 +199,7 @@ where
println!(""); println!("");
} }
// Initialize VM with an empty OpPointer // 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 { loop {
// print prompt // print prompt
let line = match editor.readline(&format!("{}> ", lines.next_line())) { 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( pub fn eval_input(
&mut self, &mut self,
input: OffsetStrIter, input: OffsetStrIter,
@ -320,10 +303,7 @@ where
} }
pub fn eval_expr(&mut self, expr: Expression) -> Result<Rc<Val>, Box<dyn Error>> { pub fn eval_expr(&mut self, expr: Expression) -> Result<Rc<Val>, Box<dyn Error>> {
let mut ops_map = translate::PositionMap { let mut ops_map = translate::OpsMap::new();
ops: Vec::new(),
pos: Vec::new(),
};
translate::AST::translate_stmt( translate::AST::translate_stmt(
Statement::Expression(expr), Statement::Expression(expr),
&mut ops_map, &mut ops_map,

View File

@ -16,13 +16,13 @@ use std::collections::BTreeMap;
use std::path::PathBuf; use std::path::PathBuf;
use std::rc::Rc; use std::rc::Rc;
use super::translate::PositionMap; use super::translate::OpsMap;
use super::Error; use super::Error;
use super::OpPointer; use super::OpPointer;
/// A Cache of Op codes. /// A Cache of Op codes.
pub struct Ops { pub struct Ops {
ops: BTreeMap<PathBuf, Rc<PositionMap>>, ops: BTreeMap<PathBuf, Rc<OpsMap>>,
} }
impl Ops { impl Ops {
@ -37,10 +37,10 @@ impl Ops {
} }
} }
pub struct Entry<'a>(btree_map::Entry<'a, PathBuf, Rc<PositionMap>>); pub struct Entry<'a>(btree_map::Entry<'a, PathBuf, Rc<OpsMap>>);
impl<'a> Entry<'a> { impl<'a> Entry<'a> {
pub fn get_pointer_or_else<F: FnOnce() -> Result<PositionMap, Error>, P: Into<PathBuf>>( pub fn get_pointer_or_else<F: FnOnce() -> Result<OpsMap, Error>, P: Into<PathBuf>>(
self, self,
f: F, f: F,
path: P, path: P,

View File

@ -16,18 +16,18 @@ use std::rc::Rc;
use crate::ast::Position; use crate::ast::Position;
use super::translate::PositionMap; use super::translate::OpsMap;
use super::{Error, Op}; use super::{Error, Op};
#[derive(Debug, PartialEq, Clone)] #[derive(Debug, PartialEq, Clone)]
pub struct OpPointer { pub struct OpPointer {
pub pos_map: Rc<PositionMap>, pub pos_map: Rc<OpsMap>,
pub ptr: Option<usize>, pub ptr: Option<usize>,
pub path: Option<PathBuf>, pub path: Option<PathBuf>,
} }
impl OpPointer { impl OpPointer {
pub fn new(ops: Rc<PositionMap>) -> Self { pub fn new(ops: Rc<OpsMap>) -> Self {
// If we load an empty program what happens? // If we load an empty program what happens?
Self { Self {
pos_map: ops, pos_map: ops,

View File

@ -11,6 +11,7 @@
// 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 std::collections::BTreeMap;
use std::path::Path; use std::path::Path;
use crate::ast::{ use crate::ast::{
@ -25,19 +26,31 @@ use crate::build::opcode::{Hook, Op};
pub struct AST(); pub struct AST();
#[derive(Debug, PartialEq)] #[derive(Debug, PartialEq)]
pub struct PositionMap { pub struct OpsMap {
pub ops: Vec<Op>, pub ops: Vec<Op>,
pub pos: Vec<Position>, pub pos: Vec<Position>,
pub links: BTreeMap<String, usize>,
} }
impl PositionMap { impl OpsMap {
pub fn new() -> Self { pub fn new() -> Self {
PositionMap { OpsMap {
ops: Vec::new(), ops: Vec::new(),
pos: Vec::new(), pos: Vec::new(),
links: BTreeMap::new(),
} }
} }
pub fn with_ops(mut self, ops: Vec<Op>, pos: Vec<Position>) -> 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 { pub fn len(&self) -> usize {
self.ops.len() self.ops.len()
} }
@ -53,13 +66,13 @@ impl PositionMap {
} }
impl AST { impl AST {
pub fn translate<P: AsRef<Path>>(stmts: Vec<Statement>, root: &P) -> PositionMap { pub fn translate<P: AsRef<Path>>(stmts: Vec<Statement>, root: &P) -> OpsMap {
let mut ops = PositionMap::new(); let mut ops = OpsMap::new();
Self::translate_stmts(stmts, &mut ops, root.as_ref()); Self::translate_stmts(stmts, &mut ops, root.as_ref());
return ops; 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 { match stmt {
Statement::Expression(expr) => { Statement::Expression(expr) => {
let expr_pos = expr.pos().clone(); let expr_pos = expr.pos().clone();
@ -90,13 +103,13 @@ impl AST {
} }
} }
fn translate_stmts(stmts: Vec<Statement>, mut ops: &mut PositionMap, root: &Path) { fn translate_stmts(stmts: Vec<Statement>, mut ops: &mut OpsMap, root: &Path) {
for stmt in stmts { for stmt in stmts {
Self::translate_stmt(stmt, &mut ops, root); 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 { match expr {
Expression::Simple(v) => { Expression::Simple(v) => {
Self::translate_value(v, &mut ops, root); Self::translate_value(v, &mut ops, root);
@ -428,8 +441,10 @@ impl AST {
} }
} }
Expression::Import(def) => { 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::Val(Primitive::Str(def.path.fragment)), def.path.pos);
ops.push(Op::Runtime(Hook::Import), def.pos); ops.push(Op::Runtime(Hook::Import), def.pos);
ops.add_link(link_path);
} }
Expression::Include(def) => { Expression::Include(def) => {
ops.push(Op::Val(Primitive::Str(def.typ.fragment)), def.typ.pos); ops.push(Op::Val(Primitive::Str(def.typ.fragment)), def.typ.pos);
@ -556,7 +571,7 @@ impl AST {
pos: Position, pos: Position,
part: TemplatePart, part: TemplatePart,
elems: &mut EI, elems: &mut EI,
mut ops: &mut PositionMap, mut ops: &mut OpsMap,
place_holder: bool, place_holder: bool,
root: &Path, root: &Path,
) { ) {
@ -585,7 +600,7 @@ impl AST {
} }
fn translate_copy( fn translate_copy(
mut ops: &mut PositionMap, mut ops: &mut OpsMap,
flds: Vec<(Token, Expression)>, flds: Vec<(Token, Expression)>,
pos: Position, pos: Position,
root: &Path, root: &Path,
@ -601,7 +616,7 @@ impl AST {
ops.push(Op::PopSelf, pos); 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 { match value {
Value::Int(i) => ops.push(Op::Val(Primitive::Int(i.val)), i.pos), 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), Value::Float(f) => ops.push(Op::Val(Primitive::Float(f.val)), f.pos),

View File

@ -23,7 +23,7 @@ use super::environment::Environment;
use super::pointer::OpPointer; use super::pointer::OpPointer;
use super::runtime; use super::runtime;
use super::scope::Stack; use super::scope::Stack;
use super::translate::PositionMap; use super::translate::OpsMap;
use super::Composite::{List, Tuple}; use super::Composite::{List, Tuple};
use super::Hook; use super::Hook;
use super::Primitive::{Bool, Empty, Float, Int, Str}; use super::Primitive::{Bool, Empty, Float, Int, Str};
@ -55,7 +55,7 @@ pub struct VM {
} }
impl VM { impl VM {
pub fn new<P: Into<PathBuf>>(strict: bool, ops: Rc<PositionMap>, working_dir: P) -> Self { pub fn new<P: Into<PathBuf>>(strict: bool, ops: Rc<OpsMap>, working_dir: P) -> Self {
Self::with_pointer(strict, OpPointer::new(ops), working_dir) Self::with_pointer(strict, OpPointer::new(ops), working_dir)
} }
@ -394,10 +394,9 @@ impl VM {
pkg_pos.clone(), pkg_pos.clone(),
pkg_pos, pkg_pos,
]; ];
Some(OpPointer::new(Rc::new(PositionMap { Some(OpPointer::new(Rc::new(
ops: pkg_ops, OpsMap::new().with_ops(pkg_ops, pos_list),
pos: pos_list, )))
})))
} else { } else {
None None
}; };