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::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,
|
||||||
|
@ -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,
|
||||||
|
@ -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,
|
||||||
|
@ -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),
|
||||||
|
@ -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
|
||||||
};
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user