mirror of
https://github.com/zaphar/ucg.git
synced 2025-07-21 18:10:42 -04:00
DEV: Unify package loading to one place.
Also record the list of locations we need to import from.
This commit is contained in:
parent
8a9ee59234
commit
c18ec8c3f7
@ -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<P: Into<PathBuf>>(&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<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.
|
||||
///
|
||||
/// 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<Statement>, path: Option<PathBuf>) -> 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<PathBuf>) -> 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<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 {
|
||||
// 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<Rc<Val>, Box<dyn Error>> {
|
||||
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,
|
||||
|
@ -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<PathBuf, Rc<PositionMap>>,
|
||||
ops: BTreeMap<PathBuf, Rc<OpsMap>>,
|
||||
}
|
||||
|
||||
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> {
|
||||
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,
|
||||
f: F,
|
||||
path: P,
|
||||
|
@ -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<PositionMap>,
|
||||
pub pos_map: Rc<OpsMap>,
|
||||
pub ptr: Option<usize>,
|
||||
pub path: Option<PathBuf>,
|
||||
}
|
||||
|
||||
impl OpPointer {
|
||||
pub fn new(ops: Rc<PositionMap>) -> Self {
|
||||
pub fn new(ops: Rc<OpsMap>) -> Self {
|
||||
// If we load an empty program what happens?
|
||||
Self {
|
||||
pos_map: ops,
|
||||
|
@ -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<Op>,
|
||||
pub pos: Vec<Position>,
|
||||
pub links: BTreeMap<String, usize>,
|
||||
}
|
||||
|
||||
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<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 {
|
||||
self.ops.len()
|
||||
}
|
||||
@ -53,13 +66,13 @@ impl PositionMap {
|
||||
}
|
||||
|
||||
impl AST {
|
||||
pub fn translate<P: AsRef<Path>>(stmts: Vec<Statement>, root: &P) -> PositionMap {
|
||||
let mut ops = PositionMap::new();
|
||||
pub fn translate<P: AsRef<Path>>(stmts: Vec<Statement>, 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<Statement>, mut ops: &mut PositionMap, root: &Path) {
|
||||
fn translate_stmts(stmts: Vec<Statement>, 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),
|
||||
|
@ -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<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)
|
||||
}
|
||||
|
||||
@ -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
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user