From 3017ced8d94eb96e61c6f8bc38a90f63b0382135 Mon Sep 17 00:00:00 2001 From: Jeremy Wall Date: Wed, 28 Aug 2019 19:11:09 -0500 Subject: [PATCH] DEV: A while raft of unit test fixes for error reporting mostly. --- src/build/compile_test.rs | 65 +++++---- src/build/mod.rs | 1 + src/build/opcode/cache.rs | 18 ++- src/build/opcode/environment.rs | 22 +-- src/build/opcode/error.rs | 25 +++- src/build/opcode/mod.rs | 1 + src/build/opcode/runtime.rs | 2 +- src/build/opcode/translate.rs | 13 ++ src/build/opcode/vm.rs | 59 ++++---- src/main.rs | 238 ++++++++++++++------------------ 10 files changed, 243 insertions(+), 201 deletions(-) diff --git a/src/build/compile_test.rs b/src/build/compile_test.rs index 8c06128..1d65887 100644 --- a/src/build/compile_test.rs +++ b/src/build/compile_test.rs @@ -258,8 +258,8 @@ fn test_binary_sum_operator_wrong_type_on_rhs_compile_failure() { assert_build_failure( "1 + \"foo\";", vec![ - Regex::new(r"Expected Integer but got \(.foo.\)").unwrap(), - Regex::new(r"at line: 1, column: 5").unwrap(), + Regex::new(r"Expected Int but got String\(foo\)").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( "1 - \"foo\";", vec![ - Regex::new(r"Expected Integer but got \(.foo.\)").unwrap(), - Regex::new(r"at line: 1, column: 5").unwrap(), + Regex::new(r"Expected Int but got String\(foo\)").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( "1 * \"foo\";", vec![ - Regex::new(r"Expected Integer but got \(.foo.\)").unwrap(), - Regex::new(r"at line: 1, column: 5").unwrap(), + Regex::new(r"Expected Int but got String\(foo\)").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( "1 / \"foo\";", vec![ - Regex::new(r"Expected Integer but got \(.foo.\)").unwrap(), - Regex::new(r"at line: 1, column: 5").unwrap(), + Regex::new(r"Expected Int but got String\(foo\)").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( "1 > \"foo\";", vec![ - Regex::new(r"Expected Integer but got \(.foo.\)").unwrap(), - Regex::new(r"at line: 1, column: 5").unwrap(), + Regex::new( + 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( "1 < \"foo\";", vec![ - Regex::new(r"Expected Integer but got \(.foo.\)").unwrap(), - Regex::new(r"at line: 1, column: 5").unwrap(), + Regex::new( + 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( "1 <= \"foo\";", vec![ - Regex::new(r"Expected Integer but got \(.foo.\)").unwrap(), - Regex::new(r"at line: 1, column: 6").unwrap(), + Regex::new( + 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( "1 >= \"foo\";", vec![ - Regex::new(r"Expected Integer but got \(.foo.\)").unwrap(), - Regex::new(r"at line: 1, column: 6").unwrap(), + Regex::new( + 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( "1 == \"foo\";", vec![ - Regex::new(r"Expected Integer but got \(.foo.\)").unwrap(), - Regex::new(r"at line: 1, column: 6").unwrap(), + Regex::new( + 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![ Regex::new(r"Expected \(\}\) but got \(;\)").unwrap(), - Regex::new(r"at line: 1, column: 2").unwrap(), + Regex::new(r"at line: 1 column: 2").unwrap(), ], ) } @@ -501,7 +516,7 @@ fn test_copy_expression_not_a_tuple_compile_failure() { "let foo = 1;\nfoo{};", vec![ Regex::new(r"Expected Tuple or Module but got \(1\)").unwrap(), - Regex::new(r"at 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( "select \"a\", { b = 1, };", vec![ - Regex::new(r"Unhandled select case .a. with no default").unwrap(), - Regex::new(r"at line: 1, column: 8").unwrap(), + Regex::new(r"Unhandled select case with no default").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( "select true, { false = 1, };", vec![ - Regex::new(r"Unhandled select case true with no default").unwrap(), - Regex::new(r"at line: 1, column: 8").unwrap(), + Regex::new(r"Unhandled select case with no default").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\";", vec![ Regex::new(r"OSError: Path not found").unwrap(), - Regex::new(r"at line: 1, column: 18").unwrap(), + Regex::new(r"line: 1 column: 18").unwrap(), ], ) } diff --git a/src/build/mod.rs b/src/build/mod.rs index 4dec097..bb31ceb 100644 --- a/src/build/mod.rs +++ b/src/build/mod.rs @@ -94,6 +94,7 @@ where environment: Rc>>, working_dir: PathBuf, // FIXME(jwall): These need to be compiled and added to the op cache. + // specifically in the environment. std: Rc>, import_path: &'a Vec, pub last: Option>, diff --git a/src/build/opcode/cache.rs b/src/build/opcode/cache.rs index f0527dc..5dad8de 100644 --- a/src/build/opcode/cache.rs +++ b/src/build/opcode/cache.rs @@ -17,6 +17,7 @@ use std::path::PathBuf; use std::rc::Rc; use super::translate::PositionMap; +use super::Error; use super::OpPointer; /// A Cache of Op codes. @@ -39,12 +40,21 @@ impl Ops { pub struct Entry<'a>(btree_map::Entry<'a, String, Rc>); impl<'a> Entry<'a> { - pub fn get_pointer_or_else PositionMap, P: Into>( + pub fn get_pointer_or_else Result, P: Into>( self, f: F, path: P, - ) -> OpPointer { - let cached = self.0.or_insert_with(|| Rc::new(f())).clone(); - OpPointer::new(cached).with_path(path.into()) + ) -> Result { + let cached = match self.0 { + 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())) } } diff --git a/src/build/opcode/environment.rs b/src/build/opcode/environment.rs index 5ae7e2a..5212023 100644 --- a/src/build/opcode/environment.rs +++ b/src/build/opcode/environment.rs @@ -12,15 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. use std::collections::BTreeMap; -use std::io::{Write, Read}; -use std::rc::Rc; -use std::path::PathBuf; 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::Value; +use super::pointer::OpPointer; use super::Error; +use super::Value; use crate::convert::{ConverterRegistry, ImporterRegistry}; use crate::iter::OffsetStrIter; use crate::parse::parse; @@ -66,24 +66,24 @@ impl Environment { } pub fn get_ops_for_path(&mut self, path: &String) -> Result { - 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. let p = PathBuf::from(&path); let root = p.parent().unwrap(); // first we read in the file - let mut f = File::open(&path).unwrap(); + let mut f = File::open(&path)?; // then we parse it 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); + // FIXME(jwall): Unify BuildError and our other Error let stmts = parse(iter, None).unwrap(); // then we create an ops from it let ops = super::translate::AST::translate(stmts, &root); - ops + Ok(ops) }, &path, - ); - Ok(op_pointer) + ) } } diff --git a/src/build/opcode/error.rs b/src/build/opcode/error.rs index c226e77..3172bb6 100644 --- a/src/build/opcode/error.rs +++ b/src/build/opcode/error.rs @@ -14,6 +14,7 @@ use std::convert::From; use std::fmt; use std::fmt::Display; +use std::io; use crate::ast::Position; @@ -30,6 +31,22 @@ impl Error { 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 for Error { @@ -43,8 +60,12 @@ impl From for Error { impl From for Error { fn from(e: std::io::Error) -> Self { + let msg = match e.kind() { + io::ErrorKind::NotFound => format!("OSError: Path not found: {}", e), + _ => format!("{}", e), + }; Error { - message: format!("{}", e), + message: msg, pos: None, } } @@ -60,4 +81,4 @@ impl Display for Error { } } -impl std::error::Error for Error {} \ No newline at end of file +impl std::error::Error for Error {} diff --git a/src/build/opcode/mod.rs b/src/build/opcode/mod.rs index 8bd8987..636a643 100644 --- a/src/build/opcode/mod.rs +++ b/src/build/opcode/mod.rs @@ -17,6 +17,7 @@ use std::rc::Rc; mod cache; mod debug; pub mod environment; +#[macro_use] mod error; pub mod pointer; mod runtime; diff --git a/src/build/opcode/runtime.rs b/src/build/opcode/runtime.rs index a049e69..0ae3828 100644 --- a/src/build/opcode/runtime.rs +++ b/src/build/opcode/runtime.rs @@ -166,7 +166,7 @@ impl Builtins { stack.push((v, path_pos)); } 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()); vm.run()?; let result = Rc::new(vm.symbols_to_tuple(true)); diff --git a/src/build/opcode/translate.rs b/src/build/opcode/translate.rs index d6ab68a..2edaf59 100644 --- a/src/build/opcode/translate.rs +++ b/src/build/opcode/translate.rs @@ -266,7 +266,13 @@ impl AST { Self::translate_expr(*expr, &mut ops, root); } Expression::Fail(def) => { + let msg_pos = def.message.pos().clone(); 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); } Expression::Format(def) => { @@ -450,6 +456,7 @@ impl AST { ops.push(Op::Runtime(Hook::Range), def.pos); } Expression::Select(def) => { + let default_pos = def.val.pos().clone(); Self::translate_expr(*def.val, &mut ops, root); let mut jumps = Vec::new(); for (key, val) in def.tuple { @@ -467,6 +474,12 @@ impl AST { if let Some(default) = def.default { Self::translate_expr(*default, &mut ops, root); } else { + ops.push( + Op::Val(Primitive::Str( + "Unhandled select case with no default".to_owned(), + )), + default_pos, + ); ops.push(Op::Bang, def.pos); } let end = ops.len() - 1; diff --git a/src/build/opcode/vm.rs b/src/build/opcode/vm.rs index f5ccc77..2967662 100644 --- a/src/build/opcode/vm.rs +++ b/src/build/opcode/vm.rs @@ -460,8 +460,8 @@ where } fn op_gt(&mut self, pos: &Position) -> Result<(), Error> { - let (left, _) = self.pop()?; - let (right, _) = self.pop()?; + let (left, left_pos) = self.pop()?; + let (right, right_pos) = self.pop()?; match (left.as_ref(), right.as_ref()) { (&P(Int(i)), &P(Int(ii))) => { self.push(Rc::new(P(Bool(i > ii))), pos.clone())?; @@ -472,8 +472,8 @@ where _ => { return Err(Error::new( format!( - "Expected Numeric values of the same type but got {:?} and {:?}", - left, right + "Expected numeric values of the same type but got {:?} at {} and {:?} at {} for expression", + left, left_pos, right, right_pos, ), pos.clone(), )); @@ -483,8 +483,8 @@ where } fn op_lt(&mut self, pos: &Position) -> Result<(), Error> { - let (left, _) = self.pop()?; - let (right, _) = self.pop()?; + let (left, left_pos) = self.pop()?; + let (right, right_pos) = self.pop()?; match (left.as_ref(), right.as_ref()) { (&P(Int(i)), &P(Int(ii))) => { self.push(Rc::new(P(Bool(i < ii))), pos.clone())?; @@ -495,8 +495,8 @@ where _ => { return Err(Error::new( format!( - "Expected Numeric values of the same type but got {:?} and {:?}", - left, right + "Expected numeric values of the same type but got {:?} at {} and {:?} at {} for expression", + left, left_pos, right, right_pos, ), pos.clone(), )); @@ -506,8 +506,8 @@ where } fn op_lteq(&mut self, pos: Position) -> Result<(), Error> { - let (left, _) = self.pop()?; - let (right, _) = self.pop()?; + let (left, left_pos) = self.pop()?; + let (right, right_pos) = self.pop()?; match (left.as_ref(), right.as_ref()) { (&P(Int(i)), &P(Int(ii))) => { self.push(Rc::new(P(Bool(i <= ii))), pos)?; @@ -518,8 +518,8 @@ where _ => { return Err(Error::new( format!( - "Expected Numeric values of the same type but got {:?} and {:?}", - left, right + "Expected numeric values of the same type but got {:?} at {} and {:?} at {} for expression", + left, left_pos, right, right_pos, ), pos, )); @@ -529,8 +529,8 @@ where } fn op_gteq(&mut self, pos: Position) -> Result<(), Error> { - let (left, _) = self.pop()?; - let (right, _) = self.pop()?; + let (left, left_pos) = self.pop()?; + let (right, right_pos) = self.pop()?; match (left.as_ref(), right.as_ref()) { (&P(Int(i)), &P(Int(ii))) => { self.push(Rc::new(P(Bool(i >= ii))), pos)?; @@ -541,8 +541,8 @@ where _ => { return Err(Error::new( format!( - "Expected Numeric values of the same type but got {:?} and {:?}", - left, right + "Expected numeric values of the same type but got {:?} at {} and {:?} at {} for expression", + left, left_pos, right, right_pos, ), pos, )); @@ -554,45 +554,45 @@ where fn op_mod(&mut self, pos: Position) -> Result<(), Error> { // Adds the previous two items in the stack. let (left, _) = self.pop()?; - let (right, _) = self.pop()?; + let (right, right_pos) = self.pop()?; // 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(()) } fn op_add(&mut self, pos: Position) -> Result<(), Error> { // Adds the previous two items in the stack. let (left, _) = self.pop()?; - let (right, _) = self.pop()?; + let (right, right_pos) = self.pop()?; // 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(()) } fn op_sub(&mut self, pos: Position) -> Result<(), Error> { // Subtracts the previous two items in the stack. let (left, _) = self.pop()?; - let (right, _) = self.pop()?; + let (right, right_pos) = self.pop()?; // 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(()) } fn op_mul(&mut self, pos: Position) -> Result<(), Error> { // Multiplies the previous two items in the stack. let (left, _) = self.pop()?; - let (right, _) = self.pop()?; + let (right, right_pos) = self.pop()?; // 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(()) } fn op_div(&mut self, pos: Position) -> Result<(), Error> { // Divides the previous two items in the stack. let (left, _) = self.pop()?; - let (right, _) = self.pop()?; + let (right, right_pos) = self.pop()?; // 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(()) } @@ -670,7 +670,12 @@ where } 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> { diff --git a/src/main.rs b/src/main.rs index 2a5c076..adbcc33 100644 --- a/src/main.rs +++ b/src/main.rs @@ -22,6 +22,7 @@ use std::collections::BTreeMap; use std::error::Error; use std::fs::File; use std::io; +use std::io::{Stdout, Stderr}; use std::io::Read; use std::path::{Path, PathBuf}; use std::process; @@ -96,47 +97,46 @@ fn run_converter(c: &dyn traits::Converter, v: Rc, f: Option<&str>) -> trai result } -fn build_file<'a, C: Cache>( +fn build_file<'a>( file: &'a str, validate: bool, strict: bool, import_paths: &'a Vec, - cache: Rc>, - registry: &'a ConverterRegistry, -) -> Result, Box> { +) -> Result, Box> { let mut file_path_buf = PathBuf::from(file); if file_path_buf.is_relative() { file_path_buf = std::env::current_dir()?.join(file_path_buf); } + let out = std::io::stdout(); + let err = std::io::stderr(); let mut builder = - build::FileBuilder::new(std::env::current_dir()?, import_paths, cache, registry); - builder.set_strict(strict); + build::FileBuilder::new(std::env::current_dir()?, import_paths, out, err); + // FIXME(jwall): builder.set_strict(strict); if validate { builder.enable_validate_mode(); } builder.build(file_path_buf)?; if validate { - println!("{}", builder.assert_collector.summary); + // FIXME(jwall): println!("{}", builder.assert_collector.summary); } Ok(builder) } -fn do_validate( +fn do_validate( file: &str, strict: bool, import_paths: &Vec, - cache: Rc>, - registry: &ConverterRegistry, ) -> bool { println!("Validating {}", file); - match build_file(file, true, strict, import_paths, cache, registry) { + match build_file(file, true, strict, import_paths) { Ok(b) => { - if b.assert_collector.success { - println!("File {} Pass\n", file); - } else { - println!("File {} Fail\n", file); + // FIXM(jwall): assert collector access. + //if b.assert_collector.success { + // println!("File {} Pass\n", file); + //} else { + // println!("File {} Fail\n", file); return false; - } + //} } Err(msg) => { eprintln!("Err: {}", msg); @@ -149,7 +149,6 @@ fn do_validate( fn process_output( output: &Option<(String, Rc)>, file: Option<&str>, - registry: &ConverterRegistry, ) -> bool { let (typ, val) = match output { Some((ref typ, ref val)) => (typ, val.clone()), @@ -157,48 +156,46 @@ fn process_output( return false; } }; - match registry.get_converter(typ) { - Some(converter) => { - run_converter(converter, val, file).unwrap(); - eprintln!("\nConversion successful"); - return true; - } - None => { - eprintln!("No such converter {}", typ); + // FIXME(jwall): Is this function even still necessary? + //match registry.get_converter(typ) { + // Some(converter) => { + // run_converter(converter, val, file).unwrap(); + // eprintln!("\nConversion successful"); + // return true; + // } + // None => { + // eprintln!("No such converter {}", typ); return false; - } - } + // } + //} } -fn do_compile( +fn do_compile( file: &str, strict: bool, import_paths: &Vec, - cache: Rc>, - registry: &ConverterRegistry, ) -> bool { 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, Err(err) => { eprintln!("{}", err); return false; } }; - if builder.out_lock.is_none() { + if builder.out.is_none() { 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( +fn visit_ucg_files( path: &Path, recurse: bool, validate: bool, strict: bool, import_paths: &Vec, - cache: Rc>, - registry: &ConverterRegistry, ) -> Result> { let our_path = String::from(path.to_string_lossy()); let mut result = true; @@ -222,8 +219,6 @@ fn visit_ucg_files( validate, strict, import_paths, - cache.clone(), - registry, ) { eprintln!("{}", e); result = false; @@ -234,8 +229,6 @@ fn visit_ucg_files( &path_as_string, strict, import_paths, - cache.clone(), - registry, ) { result = false; summary.push_str(format!("{} - FAIL\n", path_as_string).as_str()) @@ -247,8 +240,6 @@ fn visit_ucg_files( &path_as_string, strict, import_paths, - cache.clone(), - registry, ) { result = false; } @@ -256,14 +247,14 @@ fn visit_ucg_files( } } } 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; summary.push_str(format!("{} - FAIL\n", our_path).as_str()); } else { summary.push_str(format!("{} - PASS\n", &our_path).as_str()); } } else if !validate { - if !do_compile(&our_path, strict, import_paths, cache, registry) { + if !do_compile(&our_path, strict, import_paths) { result = false; } } @@ -274,11 +265,9 @@ fn visit_ucg_files( Ok(result) } -fn inspect_command( +fn inspect_command( matches: &clap::ArgMatches, import_paths: &Vec, - cache: Rc>, - registry: &ConverterRegistry, strict: bool, ) { let file = matches.value_of("INPUT"); @@ -287,66 +276,65 @@ fn inspect_command( let mut builder = build::FileBuilder::new( std::env::current_dir().unwrap(), import_paths, - cache, - registry, + io::stdout(), + io::stderr(), ); - builder.set_strict(strict); - match registry.get_converter(target) { - Some(converter) => { - if let Some(file) = file { - if let Err(e) = builder.build(file) { - eprintln!("{:?}", e); - process::exit(1); - } - } - let val = match sym { - Some(sym_name) => { - let normalized = if !sym_name.ends_with(";") { - let mut temp = sym_name.to_owned(); - temp.push_str(";"); - temp - } else { - sym_name.to_owned() - }; - let mut builder = builder.clone_builder(); - match builder.eval_string(&normalized) { - Ok(v) => Some(v.clone()), - Err(e) => { - eprintln!("{}", e); - process::exit(1); - } - } - } - None => builder.last, - }; - match val { - Some(value) => { - // We use None here because we always output to stdout for an inspect. - run_converter(converter, value, None).unwrap(); - println!(""); - process::exit(0); - } - None => { - eprintln!("No value."); - process::exit(1); - } - } - } - None => { - eprintln!( - "No such format {}\nrun `ucg converters` to see available formats.", - target - ); - process::exit(1); - } - } + // FIXME(jwall): builder.set_strict(strict); + // FIXME(jwall): Converting a value should be built into our builder? + //match registry.get_converter(target) { + // Some(converter) => { + // if let Some(file) = file { + // if let Err(e) = builder.build(file) { + // eprintln!("{:?}", e); + // process::exit(1); + // } + // } + // let val = match sym { + // Some(sym_name) => { + // let normalized = if !sym_name.ends_with(";") { + // let mut temp = sym_name.to_owned(); + // temp.push_str(";"); + // temp + // } else { + // sym_name.to_owned() + // }; + // let mut builder = builder.clone_builder(); + // match builder.eval_string(&normalized) { + // Ok(v) => Some(v.clone()), + // Err(e) => { + // eprintln!("{}", e); + // process::exit(1); + // } + // } + // } + // None => builder.last, + // }; + // match val { + // Some(value) => { + // // We use None here because we always output to stdout for an inspect. + // run_converter(converter, value, None).unwrap(); + // println!(""); + // process::exit(0); + // } + // None => { + // eprintln!("No value."); + // process::exit(1); + // } + // } + // } + // None => { + // eprintln!( + // "No such format {}\nrun `ucg converters` to see available formats.", + // target + // ); + // process::exit(1); + // } + //} } -fn build_command( +fn build_command( matches: &clap::ArgMatches, import_paths: &Vec, - cache: Rc>, - registry: &ConverterRegistry, strict: bool, ) { let files = matches.values_of("INPUT"); @@ -360,8 +348,6 @@ fn build_command( false, strict, import_paths, - cache.clone(), - ®istry, ); if let Ok(false) = ok { process::exit(1) @@ -376,8 +362,6 @@ fn build_command( false, strict, import_paths, - cache.clone(), - ®istry, ) { ok = false; } @@ -450,11 +434,9 @@ fn fmt_command(matches: &clap::ArgMatches) -> std::result::Result<(), Box( +fn test_command( matches: &clap::ArgMatches, import_paths: &Vec, - cache: Rc>, - registry: &ConverterRegistry, strict: bool, ) { let files = matches.values_of("INPUT"); @@ -467,8 +449,6 @@ fn test_command( true, strict, import_paths, - cache.clone(), - ®istry, ); if let Ok(false) = ok { process::exit(1) @@ -484,8 +464,6 @@ fn test_command( true, strict, import_paths, - cache.clone(), - ®istry, ) { ok = false; } @@ -545,10 +523,8 @@ fn print_repl_help() { println!(include_str!("help/repl.txt")); } -fn do_repl( +fn do_repl( import_paths: &Vec, - cache: Rc>, - registry: &ConverterRegistry, ) -> std::result::Result<(), Box> { let config = rustyline::Config::builder(); let mut editor = rustyline::Editor::<()>::with_config( @@ -582,7 +558,7 @@ fn do_repl( } } 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 let mut lines = ucglib::io::StatementAccumulator::new(); println!("Welcome to the UCG repl. Ctrl-D to exit"); @@ -608,9 +584,10 @@ fn do_repl( pos: ucglib::ast::Position::new(0, 0, 0), val: args[0].to_string(), }; - if let None = builder.scope_mut().build_output.remove(&key) { - eprintln!("No such binding {}", key.val); - } + // FIXME(jwall): handle this in an actual repl driver? + //if let None = builder.scope_mut().build_output.remove(&key) { + // eprintln!("No such binding {}", key.val); + //} } } else { eprintln!("Invalid repl command..."); @@ -630,9 +607,9 @@ fn do_repl( // print the result Err(e) => eprintln!("{}", e), Ok(v) => { - if builder.out_lock.is_some() { - process_output(&builder.out_lock, None, registry); - builder.out_lock = None; + if builder.out.is_some() { + // FIXME(jwall): process_output(&builder.out, None); + builder.out = None; } else { println!("{}", v); editor.history_mut().add(stmt); @@ -649,12 +626,10 @@ fn do_repl( } } -fn repl( +fn repl( import_paths: &Vec, - cache: Rc>, - registry: &ConverterRegistry, ) { - if let Err(e) = do_repl(import_paths, cache, registry) { + if let Err(e) = do_repl(import_paths) { eprintln!("{}", e); process::exit(1); } @@ -663,6 +638,7 @@ fn repl( fn main() { let mut app = do_flags(); 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 registry = ConverterRegistry::make_registry(); let mut import_paths = Vec::new(); @@ -685,11 +661,11 @@ fn main() { true }; 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") { - build_command(matches, &import_paths, cache, ®istry, strict); + build_command(matches, &import_paths, strict); } 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") { converters_command(matches, ®istry) } else if let Some(_) = app_matches.subcommand_matches("importers") { @@ -698,7 +674,7 @@ fn main() { } else if let Some(_) = app_matches.subcommand_matches("env") { env_help() } 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") { if let Err(e) = fmt_command(matches) { eprintln!("{}", e);