mirror of
https://github.com/zaphar/ucg.git
synced 2025-07-25 18:49:50 -04:00
DEV: More of the ucg commandline works now.
This commit is contained in:
parent
b3fd37a6b5
commit
d092fba5e8
@ -88,10 +88,10 @@ impl AssertCollector {
|
|||||||
/// Builder handles building ucg code for a single file.
|
/// Builder handles building ucg code for a single file.
|
||||||
pub struct FileBuilder<'a, Stdout, Stderr>
|
pub struct FileBuilder<'a, Stdout, Stderr>
|
||||||
where
|
where
|
||||||
Stdout: std::io::Write,
|
Stdout: std::io::Write + Clone,
|
||||||
Stderr: std::io::Write,
|
Stderr: std::io::Write + Clone,
|
||||||
{
|
{
|
||||||
environment: Rc<RefCell<Environment<Stdout, Stderr>>>,
|
pub 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.
|
// specifically in the environment.
|
||||||
@ -104,8 +104,8 @@ where
|
|||||||
|
|
||||||
impl<'a, Stdout, Stderr> FileBuilder<'a, Stdout, Stderr>
|
impl<'a, Stdout, Stderr> FileBuilder<'a, Stdout, Stderr>
|
||||||
where
|
where
|
||||||
Stdout: std::io::Write,
|
Stdout: std::io::Write + Clone,
|
||||||
Stderr: std::io::Write,
|
Stderr: std::io::Write + Clone,
|
||||||
{
|
{
|
||||||
/// Constructs a new Builder.
|
/// Constructs a new Builder.
|
||||||
pub fn new<P: Into<PathBuf>>(
|
pub fn new<P: Into<PathBuf>>(
|
||||||
@ -148,7 +148,7 @@ where
|
|||||||
f.read_to_string(&mut s)?;
|
f.read_to_string(&mut s)?;
|
||||||
let input = OffsetStrIter::new(&s).with_src_file(file.clone());
|
let input = OffsetStrIter::new(&s).with_src_file(file.clone());
|
||||||
// TODO(jwall): Pass in the file name?
|
// TODO(jwall): Pass in the file name?
|
||||||
let eval_result = self.eval_input(input);
|
let eval_result = self.eval_input(input, Some(file.clone()));
|
||||||
match eval_result {
|
match eval_result {
|
||||||
Ok(v) => {
|
Ok(v) => {
|
||||||
self.last = Some(v);
|
self.last = Some(v);
|
||||||
@ -187,10 +187,13 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Builds a list of parsed UCG Statements.
|
/// Builds a list of parsed UCG Statements.
|
||||||
pub fn eval_stmts(&mut self, ast: Vec<Statement>) -> BuildResult {
|
pub fn eval_stmts(&mut self, ast: Vec<Statement>, path: Option<PathBuf>) -> BuildResult {
|
||||||
// We should probably stash this in an op_cache somewhere?
|
// We should probably stash this in an op_cache somewhere?
|
||||||
let ops = translate::AST::translate(ast, &self.working_dir);
|
let ops = translate::AST::translate(ast, &self.working_dir);
|
||||||
let mut vm = VM::new(Rc::new(ops), self.environment.clone(), &self.working_dir);
|
let mut vm = VM::new(Rc::new(ops), self.environment.clone(), &self.working_dir);
|
||||||
|
if path.is_some() {
|
||||||
|
vm.set_path(path.unwrap());
|
||||||
|
}
|
||||||
if self.validate_mode {
|
if self.validate_mode {
|
||||||
vm.enable_validate_mode();
|
vm.enable_validate_mode();
|
||||||
}
|
}
|
||||||
@ -199,10 +202,14 @@ where
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn eval_input(&mut self, input: OffsetStrIter) -> Result<Rc<Val>, Box<dyn Error>> {
|
pub fn eval_input(
|
||||||
|
&mut self,
|
||||||
|
input: OffsetStrIter,
|
||||||
|
path: Option<PathBuf>,
|
||||||
|
) -> Result<Rc<Val>, Box<dyn Error>> {
|
||||||
match parse(input.clone(), None) {
|
match parse(input.clone(), None) {
|
||||||
Ok(stmts) => {
|
Ok(stmts) => {
|
||||||
self.eval_stmts(stmts)?;
|
self.eval_stmts(stmts, path)?;
|
||||||
if let Some(v) = self.out.clone() {
|
if let Some(v) = self.out.clone() {
|
||||||
return Ok(v);
|
return Ok(v);
|
||||||
}
|
}
|
||||||
@ -214,7 +221,7 @@ where
|
|||||||
|
|
||||||
/// Evaluate an input string as UCG.
|
/// Evaluate an input string as UCG.
|
||||||
pub fn eval_string(&mut self, input: &str) -> Result<Rc<Val>, Box<dyn Error>> {
|
pub fn eval_string(&mut self, input: &str) -> Result<Rc<Val>, Box<dyn Error>> {
|
||||||
self.eval_input(OffsetStrIter::new(input))
|
self.eval_input(OffsetStrIter::new(input), None)
|
||||||
}
|
}
|
||||||
|
|
||||||
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>> {
|
||||||
|
@ -55,6 +55,8 @@ impl<'a> Entry<'a> {
|
|||||||
v
|
v
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
Ok(OpPointer::new(cached).with_path(path.into()))
|
let mut ptr = OpPointer::new(cached);
|
||||||
|
ptr.set_path(path.into());
|
||||||
|
Ok(ptr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,6 +22,7 @@ use super::pointer::OpPointer;
|
|||||||
use super::Error;
|
use super::Error;
|
||||||
use super::Value;
|
use super::Value;
|
||||||
use crate::build::AssertCollector;
|
use crate::build::AssertCollector;
|
||||||
|
use crate::build::Val;
|
||||||
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;
|
||||||
@ -29,8 +30,8 @@ use crate::parse::parse;
|
|||||||
// Shared Environmental between VM's for runtime usage.
|
// Shared Environmental between VM's for runtime usage.
|
||||||
pub struct Environment<Stdout, Stderr>
|
pub struct Environment<Stdout, Stderr>
|
||||||
where
|
where
|
||||||
Stdout: Write,
|
Stdout: Write + Clone,
|
||||||
Stderr: Write,
|
Stderr: Write + Clone,
|
||||||
{
|
{
|
||||||
pub val_cache: BTreeMap<String, Rc<Value>>,
|
pub val_cache: BTreeMap<String, Rc<Value>>,
|
||||||
pub op_cache: cache::Ops,
|
pub op_cache: cache::Ops,
|
||||||
@ -43,7 +44,7 @@ where
|
|||||||
pub out_lock: BTreeSet<PathBuf>,
|
pub out_lock: BTreeSet<PathBuf>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<Stdout: Write, Stderr: Write> Environment<Stdout, Stderr> {
|
impl<Stdout: Write + Clone, Stderr: Write + Clone> Environment<Stdout, Stderr> {
|
||||||
pub fn new(out: Stdout, err: Stderr) -> Self {
|
pub fn new(out: Stdout, err: Stderr) -> Self {
|
||||||
Self::new_with_vars(out, err, BTreeMap::new())
|
Self::new_with_vars(out, err, BTreeMap::new())
|
||||||
}
|
}
|
||||||
@ -111,4 +112,32 @@ impl<Stdout: Write, Stderr: Write> Environment<Stdout, Stderr> {
|
|||||||
pub fn reset_out_lock_for_path<P: AsRef<Path>>(&mut self, path: P) {
|
pub fn reset_out_lock_for_path<P: AsRef<Path>>(&mut self, path: P) {
|
||||||
self.out_lock.remove(path.as_ref());
|
self.out_lock.remove(path.as_ref());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn stdout(&self) -> Stdout {
|
||||||
|
self.stdout.clone()
|
||||||
|
}
|
||||||
|
pub fn stderr(&self) -> Stderr {
|
||||||
|
self.stderr.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn convert_val(&mut self, typ: &str, writer: &mut dyn Write, val: Rc<Val>) -> bool {
|
||||||
|
match self.converter_registry.get_converter(typ) {
|
||||||
|
Some(c) => {
|
||||||
|
if let Err(e) = c.convert(val, writer) {
|
||||||
|
writeln!(&mut self.stderr, "{}", e).unwrap();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
writeln!(
|
||||||
|
&mut self.stderr,
|
||||||
|
"No such format {}\nrun `ucg converters` to see available formats.",
|
||||||
|
typ
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -36,9 +36,8 @@ impl OpPointer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn with_path(mut self, path: PathBuf) -> Self {
|
pub fn set_path(&mut self, path: PathBuf) {
|
||||||
self.path = Some(path);
|
self.path = Some(path);
|
||||||
self
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn next(&mut self) -> Option<&Op> {
|
pub fn next(&mut self) -> Option<&Op> {
|
||||||
|
@ -65,10 +65,10 @@ impl Builtins {
|
|||||||
pos: Position,
|
pos: Position,
|
||||||
) -> Result<(), Error>
|
) -> Result<(), Error>
|
||||||
where
|
where
|
||||||
P: AsRef<Path>,
|
P: AsRef<Path> + Debug,
|
||||||
WP: Into<PathBuf> + Clone + Debug,
|
WP: Into<PathBuf> + Clone + Debug,
|
||||||
O: std::io::Write,
|
O: std::io::Write + Clone,
|
||||||
E: std::io::Write,
|
E: std::io::Write + Clone,
|
||||||
{
|
{
|
||||||
match h {
|
match h {
|
||||||
Hook::Import => self.import(working_dir, stack, env, import_stack, pos),
|
Hook::Import => self.import(working_dir, stack, env, import_stack, pos),
|
||||||
@ -168,8 +168,8 @@ impl Builtins {
|
|||||||
pos: Position,
|
pos: Position,
|
||||||
) -> Result<(), Error>
|
) -> Result<(), Error>
|
||||||
where
|
where
|
||||||
O: std::io::Write,
|
O: std::io::Write + Clone,
|
||||||
E: std::io::Write,
|
E: std::io::Write + Clone,
|
||||||
P: Into<PathBuf> + Clone + Debug,
|
P: Into<PathBuf> + Clone + Debug,
|
||||||
{
|
{
|
||||||
let path = stack.pop();
|
let path = stack.pop();
|
||||||
@ -219,8 +219,8 @@ impl Builtins {
|
|||||||
pos: Position,
|
pos: Position,
|
||||||
) -> Result<(), Error>
|
) -> Result<(), Error>
|
||||||
where
|
where
|
||||||
O: std::io::Write,
|
O: std::io::Write + Clone,
|
||||||
E: std::io::Write,
|
E: std::io::Write + Clone,
|
||||||
P: Into<PathBuf> + Clone + Debug,
|
P: Into<PathBuf> + Clone + Debug,
|
||||||
{
|
{
|
||||||
let path = stack.pop();
|
let path = stack.pop();
|
||||||
@ -282,8 +282,8 @@ impl Builtins {
|
|||||||
env: Rc<RefCell<Environment<O, E>>>,
|
env: Rc<RefCell<Environment<O, E>>>,
|
||||||
) -> Result<(), Error>
|
) -> Result<(), Error>
|
||||||
where
|
where
|
||||||
O: std::io::Write,
|
O: std::io::Write + Clone,
|
||||||
E: std::io::Write,
|
E: std::io::Write + Clone,
|
||||||
{
|
{
|
||||||
if let Some((tuple, tpl_pos)) = stack.pop() {
|
if let Some((tuple, tpl_pos)) = stack.pop() {
|
||||||
if let &Value::C(Tuple(ref tuple_flds, _)) = tuple.as_ref() {
|
if let &Value::C(Tuple(ref tuple_flds, _)) = tuple.as_ref() {
|
||||||
@ -334,7 +334,7 @@ impl Builtins {
|
|||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
fn out<P: AsRef<Path>, O, E>(
|
fn out<P, O, E>(
|
||||||
&self,
|
&self,
|
||||||
path: Option<P>,
|
path: Option<P>,
|
||||||
stack: &mut Vec<(Rc<Value>, Position)>,
|
stack: &mut Vec<(Rc<Value>, Position)>,
|
||||||
@ -342,17 +342,19 @@ impl Builtins {
|
|||||||
pos: Position,
|
pos: Position,
|
||||||
) -> Result<(), Error>
|
) -> Result<(), Error>
|
||||||
where
|
where
|
||||||
O: std::io::Write,
|
O: std::io::Write + Clone,
|
||||||
E: std::io::Write,
|
E: std::io::Write + Clone,
|
||||||
|
P: AsRef<Path> + Debug,
|
||||||
{
|
{
|
||||||
let mut writer: Box<dyn std::io::Write> = if let Some(path) = path {
|
let write_path: Option<PathBuf> = if let Some(path) = path {
|
||||||
if env.borrow().get_out_lock_for_path(path.as_ref()) {
|
let write_path = path.as_ref().to_path_buf();
|
||||||
|
if env.borrow().get_out_lock_for_path(&path) {
|
||||||
return Err(Error::new(
|
return Err(Error::new(
|
||||||
format!("You can only have one output per file"),
|
format!("You can only have one output per file"),
|
||||||
pos));
|
pos));
|
||||||
}
|
}
|
||||||
env.borrow_mut().set_out_lock_for_path(path.as_ref());
|
env.borrow_mut().set_out_lock_for_path(path.as_ref());
|
||||||
Box::new(File::create(path)?)
|
Some(write_path)
|
||||||
} else {
|
} else {
|
||||||
if env.borrow().get_out_lock_for_path("/dev/stdout") {
|
if env.borrow().get_out_lock_for_path("/dev/stdout") {
|
||||||
return Err(Error::new(
|
return Err(Error::new(
|
||||||
@ -360,7 +362,7 @@ impl Builtins {
|
|||||||
pos));
|
pos));
|
||||||
}
|
}
|
||||||
env.borrow_mut().set_out_lock_for_path("/dev/stdout");
|
env.borrow_mut().set_out_lock_for_path("/dev/stdout");
|
||||||
Box::new(std::io::stdout())
|
None
|
||||||
};
|
};
|
||||||
let val = stack.pop();
|
let val = stack.pop();
|
||||||
if let Some((val, val_pos)) = val {
|
if let Some((val, val_pos)) = val {
|
||||||
@ -368,7 +370,15 @@ impl Builtins {
|
|||||||
let c_type = stack.pop();
|
let c_type = stack.pop();
|
||||||
if let Some((c_type_val, c_type_pos)) = c_type {
|
if let Some((c_type_val, c_type_pos)) = c_type {
|
||||||
if let &Value::P(Primitive::Str(ref c_type)) = c_type_val.as_ref() {
|
if let &Value::P(Primitive::Str(ref c_type)) = c_type_val.as_ref() {
|
||||||
|
let stdout = env.borrow().stdout();
|
||||||
if let Some(c) = env.borrow().converter_registry.get_converter(c_type) {
|
if let Some(c) = env.borrow().converter_registry.get_converter(c_type) {
|
||||||
|
let mut writer: Box<dyn std::io::Write> = match write_path {
|
||||||
|
Some(p) => {
|
||||||
|
let p = p.with_extension(c.file_ext());
|
||||||
|
Box::new(File::create(&p)?)
|
||||||
|
},
|
||||||
|
None => Box::new(stdout),
|
||||||
|
};
|
||||||
if let Err(e) = c.convert(Rc::new(val), &mut writer) {
|
if let Err(e) = c.convert(Rc::new(val), &mut writer) {
|
||||||
return Err(Error::new(format!("{}", e), pos.clone()));
|
return Err(Error::new(format!("{}", e), pos.clone()));
|
||||||
}
|
}
|
||||||
@ -396,8 +406,8 @@ impl Builtins {
|
|||||||
pos: Position,
|
pos: Position,
|
||||||
) -> Result<(), Error>
|
) -> Result<(), Error>
|
||||||
where
|
where
|
||||||
O: std::io::Write,
|
O: std::io::Write + Clone,
|
||||||
E: std::io::Write,
|
E: std::io::Write + Clone,
|
||||||
{
|
{
|
||||||
let val = stack.pop();
|
let val = stack.pop();
|
||||||
if let Some((val, val_pos)) = val {
|
if let Some((val, val_pos)) = val {
|
||||||
@ -442,8 +452,8 @@ impl Builtins {
|
|||||||
pos: Position,
|
pos: Position,
|
||||||
) -> Result<(), Error>
|
) -> Result<(), Error>
|
||||||
where
|
where
|
||||||
O: std::io::Write,
|
O: std::io::Write + Clone,
|
||||||
E: std::io::Write,
|
E: std::io::Write + Clone,
|
||||||
{
|
{
|
||||||
// get the list from the stack
|
// get the list from the stack
|
||||||
let (list, list_pos) = if let Some(list) = stack.pop() {
|
let (list, list_pos) = if let Some(list) = stack.pop() {
|
||||||
@ -554,8 +564,8 @@ impl Builtins {
|
|||||||
pos: Position,
|
pos: Position,
|
||||||
) -> Result<(), Error>
|
) -> Result<(), Error>
|
||||||
where
|
where
|
||||||
O: std::io::Write,
|
O: std::io::Write + Clone,
|
||||||
E: std::io::Write,
|
E: std::io::Write + Clone,
|
||||||
{
|
{
|
||||||
// get the list from the stack
|
// get the list from the stack
|
||||||
let (list, list_pos) = if let Some(list) = stack.pop() {
|
let (list, list_pos) = if let Some(list) = stack.pop() {
|
||||||
@ -700,8 +710,8 @@ impl Builtins {
|
|||||||
pos: Position,
|
pos: Position,
|
||||||
) -> Result<(), Error>
|
) -> Result<(), Error>
|
||||||
where
|
where
|
||||||
O: std::io::Write,
|
O: std::io::Write + Clone,
|
||||||
E: std::io::Write,
|
E: std::io::Write + Clone,
|
||||||
{
|
{
|
||||||
// get the list from the stack
|
// get the list from the stack
|
||||||
let (list, list_pos) = if let Some(list) = stack.pop() {
|
let (list, list_pos) = if let Some(list) = stack.pop() {
|
||||||
@ -839,8 +849,8 @@ impl Builtins {
|
|||||||
env: Rc<RefCell<Environment<O, E>>>,
|
env: Rc<RefCell<Environment<O, E>>>,
|
||||||
) -> Result<(), Error>
|
) -> Result<(), Error>
|
||||||
where
|
where
|
||||||
O: std::io::Write,
|
O: std::io::Write + Clone,
|
||||||
E: std::io::Write,
|
E: std::io::Write + Clone,
|
||||||
{
|
{
|
||||||
let (val, val_pos) = if let Some(val) = stack.pop() {
|
let (val, val_pos) = if let Some(val) = stack.pop() {
|
||||||
val
|
val
|
||||||
|
@ -43,8 +43,8 @@ fn construct_reserved_word_set() -> BTreeSet<&'static str> {
|
|||||||
|
|
||||||
pub struct VM<O, E>
|
pub struct VM<O, E>
|
||||||
where
|
where
|
||||||
O: std::io::Write,
|
O: std::io::Write + Clone,
|
||||||
E: std::io::Write,
|
E: std::io::Write + Clone,
|
||||||
{
|
{
|
||||||
working_dir: PathBuf,
|
working_dir: PathBuf,
|
||||||
stack: Vec<(Rc<Value>, Position)>,
|
stack: Vec<(Rc<Value>, Position)>,
|
||||||
@ -60,8 +60,8 @@ where
|
|||||||
|
|
||||||
impl<'a, O, E> VM<O, E>
|
impl<'a, O, E> VM<O, E>
|
||||||
where
|
where
|
||||||
O: std::io::Write,
|
O: std::io::Write + Clone,
|
||||||
E: std::io::Write,
|
E: std::io::Write + Clone,
|
||||||
{
|
{
|
||||||
pub fn new<P: Into<PathBuf>>(
|
pub fn new<P: Into<PathBuf>>(
|
||||||
ops: Rc<PositionMap>,
|
ops: Rc<PositionMap>,
|
||||||
@ -90,6 +90,10 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn set_path(&mut self, path: PathBuf) {
|
||||||
|
self.ops.set_path(path);
|
||||||
|
}
|
||||||
|
|
||||||
pub fn to_new_pointer(mut self, ops: OpPointer) -> Self {
|
pub fn to_new_pointer(mut self, ops: OpPointer) -> Self {
|
||||||
self.ops = ops;
|
self.ops = ops;
|
||||||
self
|
self
|
||||||
|
143
src/main.rs
143
src/main.rs
@ -43,12 +43,6 @@ fn do_flags<'a, 'b>() -> clap::App<'a, 'b> {
|
|||||||
(author: crate_authors!())
|
(author: crate_authors!())
|
||||||
(about: "Universal Configuration Grammar compiler.")
|
(about: "Universal Configuration Grammar compiler.")
|
||||||
(@arg nostrict: --("no-strict") "Turn off strict checking.")
|
(@arg nostrict: --("no-strict") "Turn off strict checking.")
|
||||||
(@subcommand eval =>
|
|
||||||
(about: "Evaluate an expression with an optional ucg file as context.")
|
|
||||||
(@arg expr: --expr -e +takes_value +required "Expression to evaluate.")
|
|
||||||
(@arg target: --format +takes_value "Output type. (flags, json, env, exec) defaults to json.")
|
|
||||||
(@arg INPUT: "ucg file to use as context for the expression.")
|
|
||||||
)
|
|
||||||
(@subcommand repl =>
|
(@subcommand repl =>
|
||||||
(about: "Start the ucg repl for interactive evaluation.")
|
(about: "Start the ucg repl for interactive evaluation.")
|
||||||
)
|
)
|
||||||
@ -82,33 +76,67 @@ fn do_flags<'a, 'b>() -> clap::App<'a, 'b> {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run_converter(c: &dyn traits::Converter, v: Rc<Val>, f: Option<&str>) -> traits::ConvertResult {
|
struct StdoutWrapper(io::Stdout);
|
||||||
let mut file: Box<dyn std::io::Write> = match f {
|
|
||||||
Some(f) => {
|
impl StdoutWrapper {
|
||||||
let mut path_buf = PathBuf::from(f);
|
fn new() -> Self {
|
||||||
path_buf.set_extension(c.file_ext());
|
Self(io::stdout())
|
||||||
let new_path = path_buf.to_str().unwrap();
|
}
|
||||||
Box::new(File::create(&new_path)?)
|
|
||||||
}
|
|
||||||
None => Box::new(io::stdout()),
|
|
||||||
};
|
|
||||||
let result = c.convert(v, file.as_mut());
|
|
||||||
file.flush()?;
|
|
||||||
result
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl io::Write for StdoutWrapper {
|
||||||
|
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||||
|
self.0.write(buf)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn flush(&mut self) -> io::Result<()> {
|
||||||
|
self.0.flush()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Clone for StdoutWrapper {
|
||||||
|
fn clone(&self) -> Self {
|
||||||
|
Self(io::stdout())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct StderrWrapper(io::Stderr);
|
||||||
|
|
||||||
|
impl StderrWrapper {
|
||||||
|
fn new() -> Self {
|
||||||
|
Self(io::stderr())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl io::Write for StderrWrapper {
|
||||||
|
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||||
|
self.0.write(buf)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn flush(&mut self) -> io::Result<()> {
|
||||||
|
self.0.flush()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Clone for StderrWrapper {
|
||||||
|
fn clone(&self) -> Self {
|
||||||
|
Self(io::stderr())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO(jwall): Build sharable stdout stderr providers.
|
||||||
fn build_file<'a>(
|
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>,
|
||||||
) -> Result<build::FileBuilder<'a, Stdout, Stderr>, Box<dyn Error>> {
|
) -> Result<build::FileBuilder<'a, StdoutWrapper, StderrWrapper>, 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 out = StdoutWrapper::new();
|
||||||
let err = std::io::stderr();
|
let err = StderrWrapper::new();
|
||||||
let mut builder = build::FileBuilder::new(std::env::current_dir()?, import_paths, out, err);
|
let mut builder = build::FileBuilder::new(std::env::current_dir()?, import_paths, out, err);
|
||||||
// FIXME(jwall): builder.set_strict(strict);
|
// FIXME(jwall): builder.set_strict(strict);
|
||||||
if validate {
|
if validate {
|
||||||
@ -217,69 +245,6 @@ fn visit_ucg_files(
|
|||||||
Ok(result)
|
Ok(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn inspect_command(matches: &clap::ArgMatches, import_paths: &Vec<PathBuf>, strict: bool) {
|
|
||||||
let file = matches.value_of("INPUT");
|
|
||||||
let sym = matches.value_of("expr");
|
|
||||||
let target = matches.value_of("target").unwrap_or("json");
|
|
||||||
let mut builder = build::FileBuilder::new(
|
|
||||||
std::env::current_dir().unwrap(),
|
|
||||||
import_paths,
|
|
||||||
io::stdout(),
|
|
||||||
io::stderr(),
|
|
||||||
);
|
|
||||||
// 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(matches: &clap::ArgMatches, import_paths: &Vec<PathBuf>, strict: bool) {
|
fn build_command(matches: &clap::ArgMatches, import_paths: &Vec<PathBuf>, strict: bool) {
|
||||||
let files = matches.values_of("INPUT");
|
let files = matches.values_of("INPUT");
|
||||||
let recurse = matches.is_present("recurse");
|
let recurse = matches.is_present("recurse");
|
||||||
@ -474,8 +439,8 @@ fn do_repl(import_paths: &Vec<PathBuf>) -> std::result::Result<(), Box<dyn Error
|
|||||||
let mut builder = build::FileBuilder::new(
|
let mut builder = build::FileBuilder::new(
|
||||||
std::env::current_dir()?,
|
std::env::current_dir()?,
|
||||||
import_paths,
|
import_paths,
|
||||||
io::stdout(),
|
StdoutWrapper::new(),
|
||||||
io::stderr(),
|
StderrWrapper::new(),
|
||||||
);
|
);
|
||||||
// loop
|
// loop
|
||||||
let mut lines = ucglib::io::StatementAccumulator::new();
|
let mut lines = ucglib::io::StatementAccumulator::new();
|
||||||
@ -575,9 +540,7 @@ fn main() {
|
|||||||
} else {
|
} else {
|
||||||
true
|
true
|
||||||
};
|
};
|
||||||
if let Some(matches) = app_matches.subcommand_matches("eval") {
|
if let Some(matches) = app_matches.subcommand_matches("build") {
|
||||||
inspect_command(matches, &import_paths, strict);
|
|
||||||
} else if let Some(matches) = app_matches.subcommand_matches("build") {
|
|
||||||
build_command(matches, &import_paths, 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, strict);
|
test_command(matches, &import_paths, strict);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user