mirror of
https://github.com/zaphar/ucg.git
synced 2025-07-25 18:49:50 -04:00
DEV: A while raft of unit test fixes for error reporting mostly.
This commit is contained in:
parent
e256abfee6
commit
3017ced8d9
@ -258,8 +258,8 @@ fn test_binary_sum_operator_wrong_type_on_rhs_compile_failure() {
|
|||||||
assert_build_failure(
|
assert_build_failure(
|
||||||
"1 + \"foo\";",
|
"1 + \"foo\";",
|
||||||
vec![
|
vec![
|
||||||
Regex::new(r"Expected Integer but got \(.foo.\)").unwrap(),
|
Regex::new(r"Expected Int but got String\(foo\)").unwrap(),
|
||||||
Regex::new(r"at <eval> line: 1, column: 5").unwrap(),
|
Regex::new(r"line: 1 column: 5").unwrap(),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -269,8 +269,8 @@ fn test_binary_minus_operator_wrong_type_on_rhs_compile_failure() {
|
|||||||
assert_build_failure(
|
assert_build_failure(
|
||||||
"1 - \"foo\";",
|
"1 - \"foo\";",
|
||||||
vec![
|
vec![
|
||||||
Regex::new(r"Expected Integer but got \(.foo.\)").unwrap(),
|
Regex::new(r"Expected Int but got String\(foo\)").unwrap(),
|
||||||
Regex::new(r"at <eval> line: 1, column: 5").unwrap(),
|
Regex::new(r"line: 1 column: 5").unwrap(),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -280,8 +280,8 @@ fn test_binary_mul_operator_wrong_type_on_rhs_compile_failure() {
|
|||||||
assert_build_failure(
|
assert_build_failure(
|
||||||
"1 * \"foo\";",
|
"1 * \"foo\";",
|
||||||
vec![
|
vec![
|
||||||
Regex::new(r"Expected Integer but got \(.foo.\)").unwrap(),
|
Regex::new(r"Expected Int but got String\(foo\)").unwrap(),
|
||||||
Regex::new(r"at <eval> line: 1, column: 5").unwrap(),
|
Regex::new(r"line: 1 column: 5").unwrap(),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -291,8 +291,8 @@ fn test_binary_div_operator_wrong_type_on_rhs_compile_failure() {
|
|||||||
assert_build_failure(
|
assert_build_failure(
|
||||||
"1 / \"foo\";",
|
"1 / \"foo\";",
|
||||||
vec![
|
vec![
|
||||||
Regex::new(r"Expected Integer but got \(.foo.\)").unwrap(),
|
Regex::new(r"Expected Int but got String\(foo\)").unwrap(),
|
||||||
Regex::new(r"at <eval> line: 1, column: 5").unwrap(),
|
Regex::new(r"line: 1 column: 5").unwrap(),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -302,8 +302,11 @@ fn test_binary_gt_operator_wrong_type_on_rhs_compile_failure() {
|
|||||||
assert_build_failure(
|
assert_build_failure(
|
||||||
"1 > \"foo\";",
|
"1 > \"foo\";",
|
||||||
vec![
|
vec![
|
||||||
Regex::new(r"Expected Integer but got \(.foo.\)").unwrap(),
|
Regex::new(
|
||||||
Regex::new(r"at <eval> line: 1, column: 5").unwrap(),
|
r"Expected numeric values of the same type but got Int\(1\) at line: 1 column: 1 and String\(foo\) at line: 1 column: 5 for expression",
|
||||||
|
)
|
||||||
|
.unwrap(),
|
||||||
|
Regex::new(r"line: 1 column: 1").unwrap(),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -313,8 +316,11 @@ fn test_binary_lt_operator_wrong_type_on_rhs_compile_failure() {
|
|||||||
assert_build_failure(
|
assert_build_failure(
|
||||||
"1 < \"foo\";",
|
"1 < \"foo\";",
|
||||||
vec![
|
vec![
|
||||||
Regex::new(r"Expected Integer but got \(.foo.\)").unwrap(),
|
Regex::new(
|
||||||
Regex::new(r"at <eval> line: 1, column: 5").unwrap(),
|
r"Expected numeric values of the same type but got Int\(1\) at line: 1 column: 1 and String\(foo\) at line: 1 column: 5 for expression",
|
||||||
|
)
|
||||||
|
.unwrap(),
|
||||||
|
Regex::new(r"line: 1 column: 1").unwrap(),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -324,8 +330,11 @@ fn test_binary_lteq_operator_wrong_type_on_rhs_compile_failure() {
|
|||||||
assert_build_failure(
|
assert_build_failure(
|
||||||
"1 <= \"foo\";",
|
"1 <= \"foo\";",
|
||||||
vec![
|
vec![
|
||||||
Regex::new(r"Expected Integer but got \(.foo.\)").unwrap(),
|
Regex::new(
|
||||||
Regex::new(r"at <eval> line: 1, column: 6").unwrap(),
|
r"Expected numeric values of the same type but got Int\(1\) at line: 1 column: 1 and String\(foo\) at line: 1 column: 6 for expression",
|
||||||
|
)
|
||||||
|
.unwrap(),
|
||||||
|
Regex::new(r"line: 1 column: 1").unwrap(),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -335,8 +344,11 @@ fn test_binary_gteq_operator_wrong_type_on_rhs_compile_failure() {
|
|||||||
assert_build_failure(
|
assert_build_failure(
|
||||||
"1 >= \"foo\";",
|
"1 >= \"foo\";",
|
||||||
vec![
|
vec![
|
||||||
Regex::new(r"Expected Integer but got \(.foo.\)").unwrap(),
|
Regex::new(
|
||||||
Regex::new(r"at <eval> line: 1, column: 6").unwrap(),
|
r"Expected numeric values of the same type but got Int\(1\) at line: 1 column: 1 and String\(foo\) at line: 1 column: 6 for expression",
|
||||||
|
)
|
||||||
|
.unwrap(),
|
||||||
|
Regex::new(r"line: 1 column: 1").unwrap(),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -346,8 +358,11 @@ fn test_binary_eqeq_operator_wrong_type_on_rhs_compile_failure() {
|
|||||||
assert_build_failure(
|
assert_build_failure(
|
||||||
"1 == \"foo\";",
|
"1 == \"foo\";",
|
||||||
vec![
|
vec![
|
||||||
Regex::new(r"Expected Integer but got \(.foo.\)").unwrap(),
|
Regex::new(
|
||||||
Regex::new(r"at <eval> line: 1, column: 6").unwrap(),
|
r"Expected numeric values of the same type but got Int\(1\) at line: 1 column: 1 and String\(foo\) at line: 1 column: 5 for expression",
|
||||||
|
)
|
||||||
|
.unwrap(),
|
||||||
|
Regex::new(r"line: 1 column: 1").unwrap(),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -358,7 +373,7 @@ fn test_incomplete_tuple_compile_failure() {
|
|||||||
"{;",
|
"{;",
|
||||||
vec![
|
vec![
|
||||||
Regex::new(r"Expected \(\}\) but got \(;\)").unwrap(),
|
Regex::new(r"Expected \(\}\) but got \(;\)").unwrap(),
|
||||||
Regex::new(r"at <eval> line: 1, column: 2").unwrap(),
|
Regex::new(r"at <eval> line: 1 column: 2").unwrap(),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -501,7 +516,7 @@ fn test_copy_expression_not_a_tuple_compile_failure() {
|
|||||||
"let foo = 1;\nfoo{};",
|
"let foo = 1;\nfoo{};",
|
||||||
vec![
|
vec![
|
||||||
Regex::new(r"Expected Tuple or Module but got \(1\)").unwrap(),
|
Regex::new(r"Expected Tuple or Module but got \(1\)").unwrap(),
|
||||||
Regex::new(r"at <eval> line: 2, column: 1").unwrap(),
|
Regex::new(r"line: 2 column: 1").unwrap(),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -546,8 +561,8 @@ fn test_select_missed_case_string_no_default_compile_failure() {
|
|||||||
assert_build_failure(
|
assert_build_failure(
|
||||||
"select \"a\", { b = 1, };",
|
"select \"a\", { b = 1, };",
|
||||||
vec![
|
vec![
|
||||||
Regex::new(r"Unhandled select case .a. with no default").unwrap(),
|
Regex::new(r"Unhandled select case with no default").unwrap(),
|
||||||
Regex::new(r"at <eval> line: 1, column: 8").unwrap(),
|
Regex::new(r"line: 1 column: 8").unwrap(),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -557,8 +572,8 @@ fn test_select_missed_case_boolean_no_default_compile_failure() {
|
|||||||
assert_build_failure(
|
assert_build_failure(
|
||||||
"select true, { false = 1, };",
|
"select true, { false = 1, };",
|
||||||
vec![
|
vec![
|
||||||
Regex::new(r"Unhandled select case true with no default").unwrap(),
|
Regex::new(r"Unhandled select case with no default").unwrap(),
|
||||||
Regex::new(r"at <eval> line: 1, column: 8").unwrap(),
|
Regex::new(r"line: 1 column: 8").unwrap(),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -569,7 +584,7 @@ fn test_bad_import_path_compile_failure() {
|
|||||||
"let bad = import \"no/such/path.ucg\";",
|
"let bad = import \"no/such/path.ucg\";",
|
||||||
vec![
|
vec![
|
||||||
Regex::new(r"OSError: Path not found").unwrap(),
|
Regex::new(r"OSError: Path not found").unwrap(),
|
||||||
Regex::new(r"at <eval> line: 1, column: 18").unwrap(),
|
Regex::new(r"line: 1 column: 18").unwrap(),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -94,6 +94,7 @@ where
|
|||||||
environment: Rc<RefCell<Environment<Stdout, Stderr>>>,
|
environment: Rc<RefCell<Environment<Stdout, Stderr>>>,
|
||||||
working_dir: PathBuf,
|
working_dir: PathBuf,
|
||||||
// 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.
|
||||||
|
// specifically in the environment.
|
||||||
std: Rc<HashMap<String, &'static str>>,
|
std: Rc<HashMap<String, &'static str>>,
|
||||||
import_path: &'a Vec<PathBuf>,
|
import_path: &'a Vec<PathBuf>,
|
||||||
pub last: Option<Rc<Val>>,
|
pub last: Option<Rc<Val>>,
|
||||||
|
@ -17,6 +17,7 @@ use std::path::PathBuf;
|
|||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
use super::translate::PositionMap;
|
use super::translate::PositionMap;
|
||||||
|
use super::Error;
|
||||||
use super::OpPointer;
|
use super::OpPointer;
|
||||||
|
|
||||||
/// A Cache of Op codes.
|
/// A Cache of Op codes.
|
||||||
@ -39,12 +40,21 @@ impl Ops {
|
|||||||
pub struct Entry<'a>(btree_map::Entry<'a, String, Rc<PositionMap>>);
|
pub struct Entry<'a>(btree_map::Entry<'a, String, Rc<PositionMap>>);
|
||||||
|
|
||||||
impl<'a> Entry<'a> {
|
impl<'a> Entry<'a> {
|
||||||
pub fn get_pointer_or_else<F: FnOnce() -> PositionMap, P: Into<PathBuf>>(
|
pub fn get_pointer_or_else<F: FnOnce() -> Result<PositionMap, Error>, P: Into<PathBuf>>(
|
||||||
self,
|
self,
|
||||||
f: F,
|
f: F,
|
||||||
path: P,
|
path: P,
|
||||||
) -> OpPointer {
|
) -> Result<OpPointer, Error> {
|
||||||
let cached = self.0.or_insert_with(|| Rc::new(f())).clone();
|
let cached = match self.0 {
|
||||||
OpPointer::new(cached).with_path(path.into())
|
btree_map::Entry::Occupied(e) => {
|
||||||
|
e.get().clone()
|
||||||
|
}
|
||||||
|
btree_map::Entry::Vacant(e) => {
|
||||||
|
let v = Rc::new(f()?);
|
||||||
|
e.insert(v.clone());
|
||||||
|
v
|
||||||
|
}
|
||||||
|
};
|
||||||
|
Ok(OpPointer::new(cached).with_path(path.into()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,15 +12,15 @@
|
|||||||
// 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::collections::BTreeMap;
|
||||||
use std::io::{Write, Read};
|
|
||||||
use std::rc::Rc;
|
|
||||||
use std::path::PathBuf;
|
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
|
use std::io::{Read, Write};
|
||||||
|
use std::path::PathBuf;
|
||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
use super::pointer::OpPointer;
|
|
||||||
use super::cache;
|
use super::cache;
|
||||||
use super::Value;
|
use super::pointer::OpPointer;
|
||||||
use super::Error;
|
use super::Error;
|
||||||
|
use super::Value;
|
||||||
use crate::convert::{ConverterRegistry, ImporterRegistry};
|
use crate::convert::{ConverterRegistry, ImporterRegistry};
|
||||||
use crate::iter::OffsetStrIter;
|
use crate::iter::OffsetStrIter;
|
||||||
use crate::parse::parse;
|
use crate::parse::parse;
|
||||||
@ -66,24 +66,24 @@ impl<Stdout: Write, Stderr: Write> Environment<Stdout, Stderr> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_ops_for_path(&mut self, path: &String) -> Result<OpPointer, Error> {
|
pub fn get_ops_for_path(&mut self, path: &String) -> Result<OpPointer, Error> {
|
||||||
let op_pointer = self.op_cache.entry(path).get_pointer_or_else(
|
self.op_cache.entry(path).get_pointer_or_else(
|
||||||
|| {
|
|| {
|
||||||
// FIXME(jwall): We need to do proper error handling here.
|
// FIXME(jwall): We need to do proper error handling here.
|
||||||
let p = PathBuf::from(&path);
|
let p = PathBuf::from(&path);
|
||||||
let root = p.parent().unwrap();
|
let root = p.parent().unwrap();
|
||||||
// first we read in the file
|
// first we read in the file
|
||||||
let mut f = File::open(&path).unwrap();
|
let mut f = File::open(&path)?;
|
||||||
// then we parse it
|
// then we parse it
|
||||||
let mut contents = String::new();
|
let mut contents = String::new();
|
||||||
f.read_to_string(&mut contents).unwrap();
|
f.read_to_string(&mut contents)?;
|
||||||
let iter = OffsetStrIter::new(&contents).with_src_file(&p);
|
let iter = OffsetStrIter::new(&contents).with_src_file(&p);
|
||||||
|
// FIXME(jwall): Unify BuildError and our other Error
|
||||||
let stmts = parse(iter, None).unwrap();
|
let stmts = parse(iter, None).unwrap();
|
||||||
// then we create an ops from it
|
// then we create an ops from it
|
||||||
let ops = super::translate::AST::translate(stmts, &root);
|
let ops = super::translate::AST::translate(stmts, &root);
|
||||||
ops
|
Ok(ops)
|
||||||
},
|
},
|
||||||
&path,
|
&path,
|
||||||
);
|
)
|
||||||
Ok(op_pointer)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
use std::convert::From;
|
use std::convert::From;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::fmt::Display;
|
use std::fmt::Display;
|
||||||
|
use std::io;
|
||||||
|
|
||||||
use crate::ast::Position;
|
use crate::ast::Position;
|
||||||
|
|
||||||
@ -30,6 +31,22 @@ impl Error {
|
|||||||
pos: Some(pos),
|
pos: Some(pos),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn with_pos(mut self, pos: Position) -> Self {
|
||||||
|
self.pos = Some(pos);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! decorate_error {
|
||||||
|
($pos:expr => $result:expr) => {
|
||||||
|
match $result {
|
||||||
|
Ok(v) => Ok(v),
|
||||||
|
Err(e) => {
|
||||||
|
Err(e.with_pos($pos.clone()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<regex::Error> for Error {
|
impl From<regex::Error> for Error {
|
||||||
@ -43,8 +60,12 @@ impl From<regex::Error> for Error {
|
|||||||
|
|
||||||
impl From<std::io::Error> for Error {
|
impl From<std::io::Error> for Error {
|
||||||
fn from(e: std::io::Error) -> Self {
|
fn from(e: std::io::Error) -> Self {
|
||||||
|
let msg = match e.kind() {
|
||||||
|
io::ErrorKind::NotFound => format!("OSError: Path not found: {}", e),
|
||||||
|
_ => format!("{}", e),
|
||||||
|
};
|
||||||
Error {
|
Error {
|
||||||
message: format!("{}", e),
|
message: msg,
|
||||||
pos: None,
|
pos: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,7 @@ use std::rc::Rc;
|
|||||||
mod cache;
|
mod cache;
|
||||||
mod debug;
|
mod debug;
|
||||||
pub mod environment;
|
pub mod environment;
|
||||||
|
#[macro_use]
|
||||||
mod error;
|
mod error;
|
||||||
pub mod pointer;
|
pub mod pointer;
|
||||||
mod runtime;
|
mod runtime;
|
||||||
|
@ -166,7 +166,7 @@ impl Builtins {
|
|||||||
stack.push((v, path_pos));
|
stack.push((v, path_pos));
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
let op_pointer = borrowed_env.get_ops_for_path(path)?;
|
let op_pointer = decorate_error!(path_pos => borrowed_env.get_ops_for_path(path))?;
|
||||||
let mut vm = VM::with_pointer(op_pointer, env.clone());
|
let mut vm = VM::with_pointer(op_pointer, env.clone());
|
||||||
vm.run()?;
|
vm.run()?;
|
||||||
let result = Rc::new(vm.symbols_to_tuple(true));
|
let result = Rc::new(vm.symbols_to_tuple(true));
|
||||||
|
@ -266,7 +266,13 @@ impl AST {
|
|||||||
Self::translate_expr(*expr, &mut ops, root);
|
Self::translate_expr(*expr, &mut ops, root);
|
||||||
}
|
}
|
||||||
Expression::Fail(def) => {
|
Expression::Fail(def) => {
|
||||||
|
let msg_pos = def.message.pos().clone();
|
||||||
Self::translate_expr(*def.message, &mut ops, root);
|
Self::translate_expr(*def.message, &mut ops, root);
|
||||||
|
ops.push(
|
||||||
|
Op::Val(Primitive::Str("UserDefined: ".to_owned())),
|
||||||
|
msg_pos,
|
||||||
|
);
|
||||||
|
ops.push(Op::Add, def.pos.clone());
|
||||||
ops.push(Op::Bang, def.pos);
|
ops.push(Op::Bang, def.pos);
|
||||||
}
|
}
|
||||||
Expression::Format(def) => {
|
Expression::Format(def) => {
|
||||||
@ -450,6 +456,7 @@ impl AST {
|
|||||||
ops.push(Op::Runtime(Hook::Range), def.pos);
|
ops.push(Op::Runtime(Hook::Range), def.pos);
|
||||||
}
|
}
|
||||||
Expression::Select(def) => {
|
Expression::Select(def) => {
|
||||||
|
let default_pos = def.val.pos().clone();
|
||||||
Self::translate_expr(*def.val, &mut ops, root);
|
Self::translate_expr(*def.val, &mut ops, root);
|
||||||
let mut jumps = Vec::new();
|
let mut jumps = Vec::new();
|
||||||
for (key, val) in def.tuple {
|
for (key, val) in def.tuple {
|
||||||
@ -467,6 +474,12 @@ impl AST {
|
|||||||
if let Some(default) = def.default {
|
if let Some(default) = def.default {
|
||||||
Self::translate_expr(*default, &mut ops, root);
|
Self::translate_expr(*default, &mut ops, root);
|
||||||
} else {
|
} else {
|
||||||
|
ops.push(
|
||||||
|
Op::Val(Primitive::Str(
|
||||||
|
"Unhandled select case with no default".to_owned(),
|
||||||
|
)),
|
||||||
|
default_pos,
|
||||||
|
);
|
||||||
ops.push(Op::Bang, def.pos);
|
ops.push(Op::Bang, def.pos);
|
||||||
}
|
}
|
||||||
let end = ops.len() - 1;
|
let end = ops.len() - 1;
|
||||||
|
@ -460,8 +460,8 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn op_gt(&mut self, pos: &Position) -> Result<(), Error> {
|
fn op_gt(&mut self, pos: &Position) -> Result<(), Error> {
|
||||||
let (left, _) = self.pop()?;
|
let (left, left_pos) = self.pop()?;
|
||||||
let (right, _) = self.pop()?;
|
let (right, right_pos) = self.pop()?;
|
||||||
match (left.as_ref(), right.as_ref()) {
|
match (left.as_ref(), right.as_ref()) {
|
||||||
(&P(Int(i)), &P(Int(ii))) => {
|
(&P(Int(i)), &P(Int(ii))) => {
|
||||||
self.push(Rc::new(P(Bool(i > ii))), pos.clone())?;
|
self.push(Rc::new(P(Bool(i > ii))), pos.clone())?;
|
||||||
@ -472,8 +472,8 @@ where
|
|||||||
_ => {
|
_ => {
|
||||||
return Err(Error::new(
|
return Err(Error::new(
|
||||||
format!(
|
format!(
|
||||||
"Expected Numeric values of the same type but got {:?} and {:?}",
|
"Expected numeric values of the same type but got {:?} at {} and {:?} at {} for expression",
|
||||||
left, right
|
left, left_pos, right, right_pos,
|
||||||
),
|
),
|
||||||
pos.clone(),
|
pos.clone(),
|
||||||
));
|
));
|
||||||
@ -483,8 +483,8 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn op_lt(&mut self, pos: &Position) -> Result<(), Error> {
|
fn op_lt(&mut self, pos: &Position) -> Result<(), Error> {
|
||||||
let (left, _) = self.pop()?;
|
let (left, left_pos) = self.pop()?;
|
||||||
let (right, _) = self.pop()?;
|
let (right, right_pos) = self.pop()?;
|
||||||
match (left.as_ref(), right.as_ref()) {
|
match (left.as_ref(), right.as_ref()) {
|
||||||
(&P(Int(i)), &P(Int(ii))) => {
|
(&P(Int(i)), &P(Int(ii))) => {
|
||||||
self.push(Rc::new(P(Bool(i < ii))), pos.clone())?;
|
self.push(Rc::new(P(Bool(i < ii))), pos.clone())?;
|
||||||
@ -495,8 +495,8 @@ where
|
|||||||
_ => {
|
_ => {
|
||||||
return Err(Error::new(
|
return Err(Error::new(
|
||||||
format!(
|
format!(
|
||||||
"Expected Numeric values of the same type but got {:?} and {:?}",
|
"Expected numeric values of the same type but got {:?} at {} and {:?} at {} for expression",
|
||||||
left, right
|
left, left_pos, right, right_pos,
|
||||||
),
|
),
|
||||||
pos.clone(),
|
pos.clone(),
|
||||||
));
|
));
|
||||||
@ -506,8 +506,8 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn op_lteq(&mut self, pos: Position) -> Result<(), Error> {
|
fn op_lteq(&mut self, pos: Position) -> Result<(), Error> {
|
||||||
let (left, _) = self.pop()?;
|
let (left, left_pos) = self.pop()?;
|
||||||
let (right, _) = self.pop()?;
|
let (right, right_pos) = self.pop()?;
|
||||||
match (left.as_ref(), right.as_ref()) {
|
match (left.as_ref(), right.as_ref()) {
|
||||||
(&P(Int(i)), &P(Int(ii))) => {
|
(&P(Int(i)), &P(Int(ii))) => {
|
||||||
self.push(Rc::new(P(Bool(i <= ii))), pos)?;
|
self.push(Rc::new(P(Bool(i <= ii))), pos)?;
|
||||||
@ -518,8 +518,8 @@ where
|
|||||||
_ => {
|
_ => {
|
||||||
return Err(Error::new(
|
return Err(Error::new(
|
||||||
format!(
|
format!(
|
||||||
"Expected Numeric values of the same type but got {:?} and {:?}",
|
"Expected numeric values of the same type but got {:?} at {} and {:?} at {} for expression",
|
||||||
left, right
|
left, left_pos, right, right_pos,
|
||||||
),
|
),
|
||||||
pos,
|
pos,
|
||||||
));
|
));
|
||||||
@ -529,8 +529,8 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn op_gteq(&mut self, pos: Position) -> Result<(), Error> {
|
fn op_gteq(&mut self, pos: Position) -> Result<(), Error> {
|
||||||
let (left, _) = self.pop()?;
|
let (left, left_pos) = self.pop()?;
|
||||||
let (right, _) = self.pop()?;
|
let (right, right_pos) = self.pop()?;
|
||||||
match (left.as_ref(), right.as_ref()) {
|
match (left.as_ref(), right.as_ref()) {
|
||||||
(&P(Int(i)), &P(Int(ii))) => {
|
(&P(Int(i)), &P(Int(ii))) => {
|
||||||
self.push(Rc::new(P(Bool(i >= ii))), pos)?;
|
self.push(Rc::new(P(Bool(i >= ii))), pos)?;
|
||||||
@ -541,8 +541,8 @@ where
|
|||||||
_ => {
|
_ => {
|
||||||
return Err(Error::new(
|
return Err(Error::new(
|
||||||
format!(
|
format!(
|
||||||
"Expected Numeric values of the same type but got {:?} and {:?}",
|
"Expected numeric values of the same type but got {:?} at {} and {:?} at {} for expression",
|
||||||
left, right
|
left, left_pos, right, right_pos,
|
||||||
),
|
),
|
||||||
pos,
|
pos,
|
||||||
));
|
));
|
||||||
@ -554,45 +554,45 @@ where
|
|||||||
fn op_mod(&mut self, pos: Position) -> Result<(), Error> {
|
fn op_mod(&mut self, pos: Position) -> Result<(), Error> {
|
||||||
// Adds the previous two items in the stack.
|
// Adds the previous two items in the stack.
|
||||||
let (left, _) = self.pop()?;
|
let (left, _) = self.pop()?;
|
||||||
let (right, _) = self.pop()?;
|
let (right, right_pos) = self.pop()?;
|
||||||
// Then pushes the result onto the stack.
|
// Then pushes the result onto the stack.
|
||||||
self.push(Rc::new(P(self.modulus(&left, &right, &pos)?)), pos)?;
|
self.push(Rc::new(P(self.modulus(&left, &right, &right_pos)?)), pos)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn op_add(&mut self, pos: Position) -> Result<(), Error> {
|
fn op_add(&mut self, pos: Position) -> Result<(), Error> {
|
||||||
// Adds the previous two items in the stack.
|
// Adds the previous two items in the stack.
|
||||||
let (left, _) = self.pop()?;
|
let (left, _) = self.pop()?;
|
||||||
let (right, _) = self.pop()?;
|
let (right, right_pos) = self.pop()?;
|
||||||
// Then pushes the result onto the stack.
|
// Then pushes the result onto the stack.
|
||||||
self.push(Rc::new(self.add(&left, &right, &pos)?), pos)?;
|
self.push(Rc::new(self.add(&left, &right, &right_pos)?), pos)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn op_sub(&mut self, pos: Position) -> Result<(), Error> {
|
fn op_sub(&mut self, pos: Position) -> Result<(), Error> {
|
||||||
// Subtracts the previous two items in the stack.
|
// Subtracts the previous two items in the stack.
|
||||||
let (left, _) = self.pop()?;
|
let (left, _) = self.pop()?;
|
||||||
let (right, _) = self.pop()?;
|
let (right, right_pos) = self.pop()?;
|
||||||
// Then pushes the result onto the stack.
|
// Then pushes the result onto the stack.
|
||||||
self.push(Rc::new(P(self.sub(&left, &right, &pos)?)), pos)?;
|
self.push(Rc::new(P(self.sub(&left, &right, &right_pos)?)), pos)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn op_mul(&mut self, pos: Position) -> Result<(), Error> {
|
fn op_mul(&mut self, pos: Position) -> Result<(), Error> {
|
||||||
// Multiplies the previous two items in the stack.
|
// Multiplies the previous two items in the stack.
|
||||||
let (left, _) = self.pop()?;
|
let (left, _) = self.pop()?;
|
||||||
let (right, _) = self.pop()?;
|
let (right, right_pos) = self.pop()?;
|
||||||
// Then pushes the result onto the stack.
|
// Then pushes the result onto the stack.
|
||||||
self.push(Rc::new(P(self.mul(&left, &right, &pos)?)), pos)?;
|
self.push(Rc::new(P(self.mul(&left, &right, &right_pos)?)), pos)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn op_div(&mut self, pos: Position) -> Result<(), Error> {
|
fn op_div(&mut self, pos: Position) -> Result<(), Error> {
|
||||||
// Divides the previous two items in the stack.
|
// Divides the previous two items in the stack.
|
||||||
let (left, _) = self.pop()?;
|
let (left, _) = self.pop()?;
|
||||||
let (right, _) = self.pop()?;
|
let (right, right_pos) = self.pop()?;
|
||||||
// Then pushes the result onto the stack.
|
// Then pushes the result onto the stack.
|
||||||
self.push(Rc::new(P(self.div(&left, &right, &pos)?)), pos)?;
|
self.push(Rc::new(P(self.div(&left, &right, &right_pos)?)), pos)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -670,7 +670,12 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn op_bang(&mut self) -> Result<(), Error> {
|
fn op_bang(&mut self) -> Result<(), Error> {
|
||||||
Ok(())
|
let (msg_val, err_pos) = self.pop()?;
|
||||||
|
if let &P(Str(ref msg)) = msg_val.as_ref() {
|
||||||
|
return Err(Error::new(msg.clone(), err_pos));
|
||||||
|
} else {
|
||||||
|
unreachable!();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn op_index(&mut self, safe: bool, pos: Position) -> Result<(), Error> {
|
fn op_index(&mut self, safe: bool, pos: Position) -> Result<(), Error> {
|
||||||
|
238
src/main.rs
238
src/main.rs
@ -22,6 +22,7 @@ use std::collections::BTreeMap;
|
|||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io;
|
use std::io;
|
||||||
|
use std::io::{Stdout, Stderr};
|
||||||
use std::io::Read;
|
use std::io::Read;
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
use std::process;
|
use std::process;
|
||||||
@ -96,47 +97,46 @@ fn run_converter(c: &dyn traits::Converter, v: Rc<Val>, f: Option<&str>) -> trai
|
|||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build_file<'a, C: Cache>(
|
fn build_file<'a>(
|
||||||
file: &'a str,
|
file: &'a str,
|
||||||
validate: bool,
|
validate: bool,
|
||||||
strict: bool,
|
strict: bool,
|
||||||
import_paths: &'a Vec<PathBuf>,
|
import_paths: &'a Vec<PathBuf>,
|
||||||
cache: Rc<RefCell<C>>,
|
) -> Result<build::FileBuilder<'a, Stdout, Stderr>, Box<dyn Error>> {
|
||||||
registry: &'a ConverterRegistry,
|
|
||||||
) -> Result<build::FileBuilder<'a, C>, 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 = std::io::stdout();
|
||||||
|
let err = std::io::stderr();
|
||||||
let mut builder =
|
let mut builder =
|
||||||
build::FileBuilder::new(std::env::current_dir()?, import_paths, cache, registry);
|
build::FileBuilder::new(std::env::current_dir()?, import_paths, out, err);
|
||||||
builder.set_strict(strict);
|
// FIXME(jwall): builder.set_strict(strict);
|
||||||
if validate {
|
if validate {
|
||||||
builder.enable_validate_mode();
|
builder.enable_validate_mode();
|
||||||
}
|
}
|
||||||
builder.build(file_path_buf)?;
|
builder.build(file_path_buf)?;
|
||||||
if validate {
|
if validate {
|
||||||
println!("{}", builder.assert_collector.summary);
|
// FIXME(jwall): println!("{}", builder.assert_collector.summary);
|
||||||
}
|
}
|
||||||
Ok(builder)
|
Ok(builder)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn do_validate<C: Cache>(
|
fn do_validate(
|
||||||
file: &str,
|
file: &str,
|
||||||
strict: bool,
|
strict: bool,
|
||||||
import_paths: &Vec<PathBuf>,
|
import_paths: &Vec<PathBuf>,
|
||||||
cache: Rc<RefCell<C>>,
|
|
||||||
registry: &ConverterRegistry,
|
|
||||||
) -> bool {
|
) -> bool {
|
||||||
println!("Validating {}", file);
|
println!("Validating {}", file);
|
||||||
match build_file(file, true, strict, import_paths, cache, registry) {
|
match build_file(file, true, strict, import_paths) {
|
||||||
Ok(b) => {
|
Ok(b) => {
|
||||||
if b.assert_collector.success {
|
// FIXM(jwall): assert collector access.
|
||||||
println!("File {} Pass\n", file);
|
//if b.assert_collector.success {
|
||||||
} else {
|
// println!("File {} Pass\n", file);
|
||||||
println!("File {} Fail\n", file);
|
//} else {
|
||||||
|
// println!("File {} Fail\n", file);
|
||||||
return false;
|
return false;
|
||||||
}
|
//}
|
||||||
}
|
}
|
||||||
Err(msg) => {
|
Err(msg) => {
|
||||||
eprintln!("Err: {}", msg);
|
eprintln!("Err: {}", msg);
|
||||||
@ -149,7 +149,6 @@ fn do_validate<C: Cache>(
|
|||||||
fn process_output(
|
fn process_output(
|
||||||
output: &Option<(String, Rc<Val>)>,
|
output: &Option<(String, Rc<Val>)>,
|
||||||
file: Option<&str>,
|
file: Option<&str>,
|
||||||
registry: &ConverterRegistry,
|
|
||||||
) -> bool {
|
) -> bool {
|
||||||
let (typ, val) = match output {
|
let (typ, val) = match output {
|
||||||
Some((ref typ, ref val)) => (typ, val.clone()),
|
Some((ref typ, ref val)) => (typ, val.clone()),
|
||||||
@ -157,48 +156,46 @@ fn process_output(
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
match registry.get_converter(typ) {
|
// FIXME(jwall): Is this function even still necessary?
|
||||||
Some(converter) => {
|
//match registry.get_converter(typ) {
|
||||||
run_converter(converter, val, file).unwrap();
|
// Some(converter) => {
|
||||||
eprintln!("\nConversion successful");
|
// run_converter(converter, val, file).unwrap();
|
||||||
return true;
|
// eprintln!("\nConversion successful");
|
||||||
}
|
// return true;
|
||||||
None => {
|
// }
|
||||||
eprintln!("No such converter {}", typ);
|
// None => {
|
||||||
|
// eprintln!("No such converter {}", typ);
|
||||||
return false;
|
return false;
|
||||||
}
|
// }
|
||||||
}
|
//}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn do_compile<C: Cache>(
|
fn do_compile(
|
||||||
file: &str,
|
file: &str,
|
||||||
strict: bool,
|
strict: bool,
|
||||||
import_paths: &Vec<PathBuf>,
|
import_paths: &Vec<PathBuf>,
|
||||||
cache: Rc<RefCell<C>>,
|
|
||||||
registry: &ConverterRegistry,
|
|
||||||
) -> bool {
|
) -> bool {
|
||||||
println!("Building {}", file);
|
println!("Building {}", file);
|
||||||
let builder = match build_file(file, false, strict, import_paths, cache.clone(), registry) {
|
let builder = match build_file(file, false, strict, import_paths) {
|
||||||
Ok(builder) => builder,
|
Ok(builder) => builder,
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
eprintln!("{}", err);
|
eprintln!("{}", err);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
if builder.out_lock.is_none() {
|
if builder.out.is_none() {
|
||||||
eprintln!("Build results in no artifacts.");
|
eprintln!("Build results in no artifacts.");
|
||||||
}
|
}
|
||||||
process_output(&builder.out_lock, Some(file), registry)
|
// FIXME(jwall): tuple? process_output(&builder.out, Some(file))
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_ucg_files<C: Cache>(
|
fn visit_ucg_files(
|
||||||
path: &Path,
|
path: &Path,
|
||||||
recurse: bool,
|
recurse: bool,
|
||||||
validate: bool,
|
validate: bool,
|
||||||
strict: bool,
|
strict: bool,
|
||||||
import_paths: &Vec<PathBuf>,
|
import_paths: &Vec<PathBuf>,
|
||||||
cache: Rc<RefCell<C>>,
|
|
||||||
registry: &ConverterRegistry,
|
|
||||||
) -> 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;
|
||||||
@ -222,8 +219,6 @@ fn visit_ucg_files<C: Cache>(
|
|||||||
validate,
|
validate,
|
||||||
strict,
|
strict,
|
||||||
import_paths,
|
import_paths,
|
||||||
cache.clone(),
|
|
||||||
registry,
|
|
||||||
) {
|
) {
|
||||||
eprintln!("{}", e);
|
eprintln!("{}", e);
|
||||||
result = false;
|
result = false;
|
||||||
@ -234,8 +229,6 @@ fn visit_ucg_files<C: Cache>(
|
|||||||
&path_as_string,
|
&path_as_string,
|
||||||
strict,
|
strict,
|
||||||
import_paths,
|
import_paths,
|
||||||
cache.clone(),
|
|
||||||
registry,
|
|
||||||
) {
|
) {
|
||||||
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())
|
||||||
@ -247,8 +240,6 @@ fn visit_ucg_files<C: Cache>(
|
|||||||
&path_as_string,
|
&path_as_string,
|
||||||
strict,
|
strict,
|
||||||
import_paths,
|
import_paths,
|
||||||
cache.clone(),
|
|
||||||
registry,
|
|
||||||
) {
|
) {
|
||||||
result = false;
|
result = false;
|
||||||
}
|
}
|
||||||
@ -256,14 +247,14 @@ fn visit_ucg_files<C: Cache>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} 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, cache, registry) {
|
if !do_validate(&our_path, strict, import_paths) {
|
||||||
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, cache, registry) {
|
if !do_compile(&our_path, strict, import_paths) {
|
||||||
result = false;
|
result = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -274,11 +265,9 @@ fn visit_ucg_files<C: Cache>(
|
|||||||
Ok(result)
|
Ok(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn inspect_command<C: Cache>(
|
fn inspect_command(
|
||||||
matches: &clap::ArgMatches,
|
matches: &clap::ArgMatches,
|
||||||
import_paths: &Vec<PathBuf>,
|
import_paths: &Vec<PathBuf>,
|
||||||
cache: Rc<RefCell<C>>,
|
|
||||||
registry: &ConverterRegistry,
|
|
||||||
strict: bool,
|
strict: bool,
|
||||||
) {
|
) {
|
||||||
let file = matches.value_of("INPUT");
|
let file = matches.value_of("INPUT");
|
||||||
@ -287,66 +276,65 @@ fn inspect_command<C: Cache>(
|
|||||||
let mut builder = build::FileBuilder::new(
|
let mut builder = build::FileBuilder::new(
|
||||||
std::env::current_dir().unwrap(),
|
std::env::current_dir().unwrap(),
|
||||||
import_paths,
|
import_paths,
|
||||||
cache,
|
io::stdout(),
|
||||||
registry,
|
io::stderr(),
|
||||||
);
|
);
|
||||||
builder.set_strict(strict);
|
// FIXME(jwall): builder.set_strict(strict);
|
||||||
match registry.get_converter(target) {
|
// FIXME(jwall): Converting a value should be built into our builder?
|
||||||
Some(converter) => {
|
//match registry.get_converter(target) {
|
||||||
if let Some(file) = file {
|
// Some(converter) => {
|
||||||
if let Err(e) = builder.build(file) {
|
// if let Some(file) = file {
|
||||||
eprintln!("{:?}", e);
|
// if let Err(e) = builder.build(file) {
|
||||||
process::exit(1);
|
// eprintln!("{:?}", e);
|
||||||
}
|
// process::exit(1);
|
||||||
}
|
// }
|
||||||
let val = match sym {
|
// }
|
||||||
Some(sym_name) => {
|
// let val = match sym {
|
||||||
let normalized = if !sym_name.ends_with(";") {
|
// Some(sym_name) => {
|
||||||
let mut temp = sym_name.to_owned();
|
// let normalized = if !sym_name.ends_with(";") {
|
||||||
temp.push_str(";");
|
// let mut temp = sym_name.to_owned();
|
||||||
temp
|
// temp.push_str(";");
|
||||||
} else {
|
// temp
|
||||||
sym_name.to_owned()
|
// } else {
|
||||||
};
|
// sym_name.to_owned()
|
||||||
let mut builder = builder.clone_builder();
|
// };
|
||||||
match builder.eval_string(&normalized) {
|
// let mut builder = builder.clone_builder();
|
||||||
Ok(v) => Some(v.clone()),
|
// match builder.eval_string(&normalized) {
|
||||||
Err(e) => {
|
// Ok(v) => Some(v.clone()),
|
||||||
eprintln!("{}", e);
|
// Err(e) => {
|
||||||
process::exit(1);
|
// eprintln!("{}", e);
|
||||||
}
|
// process::exit(1);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
None => builder.last,
|
// }
|
||||||
};
|
// None => builder.last,
|
||||||
match val {
|
// };
|
||||||
Some(value) => {
|
// match val {
|
||||||
// We use None here because we always output to stdout for an inspect.
|
// Some(value) => {
|
||||||
run_converter(converter, value, None).unwrap();
|
// // We use None here because we always output to stdout for an inspect.
|
||||||
println!("");
|
// run_converter(converter, value, None).unwrap();
|
||||||
process::exit(0);
|
// println!("");
|
||||||
}
|
// process::exit(0);
|
||||||
None => {
|
// }
|
||||||
eprintln!("No value.");
|
// None => {
|
||||||
process::exit(1);
|
// eprintln!("No value.");
|
||||||
}
|
// process::exit(1);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
None => {
|
// }
|
||||||
eprintln!(
|
// None => {
|
||||||
"No such format {}\nrun `ucg converters` to see available formats.",
|
// eprintln!(
|
||||||
target
|
// "No such format {}\nrun `ucg converters` to see available formats.",
|
||||||
);
|
// target
|
||||||
process::exit(1);
|
// );
|
||||||
}
|
// process::exit(1);
|
||||||
}
|
// }
|
||||||
|
//}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build_command<C: Cache>(
|
fn build_command(
|
||||||
matches: &clap::ArgMatches,
|
matches: &clap::ArgMatches,
|
||||||
import_paths: &Vec<PathBuf>,
|
import_paths: &Vec<PathBuf>,
|
||||||
cache: Rc<RefCell<C>>,
|
|
||||||
registry: &ConverterRegistry,
|
|
||||||
strict: bool,
|
strict: bool,
|
||||||
) {
|
) {
|
||||||
let files = matches.values_of("INPUT");
|
let files = matches.values_of("INPUT");
|
||||||
@ -360,8 +348,6 @@ fn build_command<C: Cache>(
|
|||||||
false,
|
false,
|
||||||
strict,
|
strict,
|
||||||
import_paths,
|
import_paths,
|
||||||
cache.clone(),
|
|
||||||
®istry,
|
|
||||||
);
|
);
|
||||||
if let Ok(false) = ok {
|
if let Ok(false) = ok {
|
||||||
process::exit(1)
|
process::exit(1)
|
||||||
@ -376,8 +362,6 @@ fn build_command<C: Cache>(
|
|||||||
false,
|
false,
|
||||||
strict,
|
strict,
|
||||||
import_paths,
|
import_paths,
|
||||||
cache.clone(),
|
|
||||||
®istry,
|
|
||||||
) {
|
) {
|
||||||
ok = false;
|
ok = false;
|
||||||
}
|
}
|
||||||
@ -450,11 +434,9 @@ fn fmt_command(matches: &clap::ArgMatches) -> std::result::Result<(), Box<dyn Er
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_command<C: Cache>(
|
fn test_command(
|
||||||
matches: &clap::ArgMatches,
|
matches: &clap::ArgMatches,
|
||||||
import_paths: &Vec<PathBuf>,
|
import_paths: &Vec<PathBuf>,
|
||||||
cache: Rc<RefCell<C>>,
|
|
||||||
registry: &ConverterRegistry,
|
|
||||||
strict: bool,
|
strict: bool,
|
||||||
) {
|
) {
|
||||||
let files = matches.values_of("INPUT");
|
let files = matches.values_of("INPUT");
|
||||||
@ -467,8 +449,6 @@ fn test_command<C: Cache>(
|
|||||||
true,
|
true,
|
||||||
strict,
|
strict,
|
||||||
import_paths,
|
import_paths,
|
||||||
cache.clone(),
|
|
||||||
®istry,
|
|
||||||
);
|
);
|
||||||
if let Ok(false) = ok {
|
if let Ok(false) = ok {
|
||||||
process::exit(1)
|
process::exit(1)
|
||||||
@ -484,8 +464,6 @@ fn test_command<C: Cache>(
|
|||||||
true,
|
true,
|
||||||
strict,
|
strict,
|
||||||
import_paths,
|
import_paths,
|
||||||
cache.clone(),
|
|
||||||
®istry,
|
|
||||||
) {
|
) {
|
||||||
ok = false;
|
ok = false;
|
||||||
}
|
}
|
||||||
@ -545,10 +523,8 @@ fn print_repl_help() {
|
|||||||
println!(include_str!("help/repl.txt"));
|
println!(include_str!("help/repl.txt"));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn do_repl<C: Cache>(
|
fn do_repl(
|
||||||
import_paths: &Vec<PathBuf>,
|
import_paths: &Vec<PathBuf>,
|
||||||
cache: Rc<RefCell<C>>,
|
|
||||||
registry: &ConverterRegistry,
|
|
||||||
) -> std::result::Result<(), Box<dyn Error>> {
|
) -> std::result::Result<(), Box<dyn Error>> {
|
||||||
let config = rustyline::Config::builder();
|
let config = rustyline::Config::builder();
|
||||||
let mut editor = rustyline::Editor::<()>::with_config(
|
let mut editor = rustyline::Editor::<()>::with_config(
|
||||||
@ -582,7 +558,7 @@ fn do_repl<C: Cache>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
let mut builder =
|
let mut builder =
|
||||||
build::FileBuilder::new(std::env::current_dir()?, import_paths, cache, registry);
|
build::FileBuilder::new(std::env::current_dir()?, import_paths, io::stdout(), io::stderr());
|
||||||
// loop
|
// loop
|
||||||
let mut lines = ucglib::io::StatementAccumulator::new();
|
let mut lines = ucglib::io::StatementAccumulator::new();
|
||||||
println!("Welcome to the UCG repl. Ctrl-D to exit");
|
println!("Welcome to the UCG repl. Ctrl-D to exit");
|
||||||
@ -608,9 +584,10 @@ fn do_repl<C: Cache>(
|
|||||||
pos: ucglib::ast::Position::new(0, 0, 0),
|
pos: ucglib::ast::Position::new(0, 0, 0),
|
||||||
val: args[0].to_string(),
|
val: args[0].to_string(),
|
||||||
};
|
};
|
||||||
if let None = builder.scope_mut().build_output.remove(&key) {
|
// FIXME(jwall): handle this in an actual repl driver?
|
||||||
eprintln!("No such binding {}", key.val);
|
//if let None = builder.scope_mut().build_output.remove(&key) {
|
||||||
}
|
// eprintln!("No such binding {}", key.val);
|
||||||
|
//}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
eprintln!("Invalid repl command...");
|
eprintln!("Invalid repl command...");
|
||||||
@ -630,9 +607,9 @@ fn do_repl<C: Cache>(
|
|||||||
// print the result
|
// print the result
|
||||||
Err(e) => eprintln!("{}", e),
|
Err(e) => eprintln!("{}", e),
|
||||||
Ok(v) => {
|
Ok(v) => {
|
||||||
if builder.out_lock.is_some() {
|
if builder.out.is_some() {
|
||||||
process_output(&builder.out_lock, None, registry);
|
// FIXME(jwall): process_output(&builder.out, None);
|
||||||
builder.out_lock = None;
|
builder.out = None;
|
||||||
} else {
|
} else {
|
||||||
println!("{}", v);
|
println!("{}", v);
|
||||||
editor.history_mut().add(stmt);
|
editor.history_mut().add(stmt);
|
||||||
@ -649,12 +626,10 @@ fn do_repl<C: Cache>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn repl<C: Cache>(
|
fn repl(
|
||||||
import_paths: &Vec<PathBuf>,
|
import_paths: &Vec<PathBuf>,
|
||||||
cache: Rc<RefCell<C>>,
|
|
||||||
registry: &ConverterRegistry,
|
|
||||||
) {
|
) {
|
||||||
if let Err(e) = do_repl(import_paths, cache, registry) {
|
if let Err(e) = do_repl(import_paths) {
|
||||||
eprintln!("{}", e);
|
eprintln!("{}", e);
|
||||||
process::exit(1);
|
process::exit(1);
|
||||||
}
|
}
|
||||||
@ -663,6 +638,7 @@ fn repl<C: Cache>(
|
|||||||
fn main() {
|
fn main() {
|
||||||
let mut app = do_flags();
|
let mut app = do_flags();
|
||||||
let app_matches = app.clone().get_matches();
|
let app_matches = app.clone().get_matches();
|
||||||
|
// FIXME(jwall): Do we want these to be shared or not?
|
||||||
let cache = Rc::new(RefCell::new(MemoryCache::new()));
|
let cache = Rc::new(RefCell::new(MemoryCache::new()));
|
||||||
let registry = ConverterRegistry::make_registry();
|
let registry = ConverterRegistry::make_registry();
|
||||||
let mut import_paths = Vec::new();
|
let mut import_paths = Vec::new();
|
||||||
@ -685,11 +661,11 @@ fn main() {
|
|||||||
true
|
true
|
||||||
};
|
};
|
||||||
if let Some(matches) = app_matches.subcommand_matches("eval") {
|
if let Some(matches) = app_matches.subcommand_matches("eval") {
|
||||||
inspect_command(matches, &import_paths, cache, ®istry, strict);
|
inspect_command(matches, &import_paths, strict);
|
||||||
} else if let Some(matches) = app_matches.subcommand_matches("build") {
|
} else if let Some(matches) = app_matches.subcommand_matches("build") {
|
||||||
build_command(matches, &import_paths, cache, ®istry, strict);
|
build_command(matches, &import_paths, strict);
|
||||||
} 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, cache, ®istry, strict);
|
test_command(matches, &import_paths, strict);
|
||||||
} 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") {
|
||||||
@ -698,7 +674,7 @@ fn main() {
|
|||||||
} else if let Some(_) = app_matches.subcommand_matches("env") {
|
} else if let Some(_) = app_matches.subcommand_matches("env") {
|
||||||
env_help()
|
env_help()
|
||||||
} else if let Some(_) = app_matches.subcommand_matches("repl") {
|
} else if let Some(_) = app_matches.subcommand_matches("repl") {
|
||||||
repl(&import_paths, cache, ®istry)
|
repl(&import_paths)
|
||||||
} else if let Some(matches) = app_matches.subcommand_matches("fmt") {
|
} else if let Some(matches) = app_matches.subcommand_matches("fmt") {
|
||||||
if let Err(e) = fmt_command(matches) {
|
if let Err(e) = fmt_command(matches) {
|
||||||
eprintln!("{}", e);
|
eprintln!("{}", e);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user