mirror of
https://github.com/zaphar/ucg.git
synced 2025-07-22 18:19:54 -04:00
DEV: Working Trace statements
This commit is contained in:
parent
2985d4258f
commit
946a112eb4
@ -28,6 +28,8 @@ pub use vm::VM;
|
||||
use pointer::OpPointer;
|
||||
use scope::Stack;
|
||||
|
||||
use crate::ast::Position;
|
||||
|
||||
#[derive(Debug, PartialEq, Clone)]
|
||||
pub enum Primitive {
|
||||
// Primitive Types
|
||||
@ -146,6 +148,7 @@ pub enum Hook {
|
||||
Convert,
|
||||
Regex,
|
||||
Range,
|
||||
Trace(Position),
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Clone)]
|
||||
|
@ -12,9 +12,10 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
use std::collections::BTreeMap;
|
||||
use std::convert::TryFrom;
|
||||
use std::convert::TryInto;
|
||||
use std::fs::File;
|
||||
use std::io::Read;
|
||||
use std::io::{Read, Write};
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::rc::Rc;
|
||||
|
||||
@ -24,12 +25,14 @@ use super::cache;
|
||||
use super::Value::{C, F, P};
|
||||
use super::VM;
|
||||
use super::{Composite, Error, Hook, Primitive, Value};
|
||||
use crate::ast::Position;
|
||||
use crate::build::ir::Val;
|
||||
use crate::build::AssertCollector;
|
||||
use crate::convert::{ConverterRegistry, ImporterRegistry};
|
||||
use Composite::{List, Tuple};
|
||||
use Primitive::{Bool, Empty, Str, Int};
|
||||
use Primitive::{Bool, Empty, Int, Str};
|
||||
|
||||
pub struct Builtins {
|
||||
pub struct Builtins<Out: Write, Err: Write> {
|
||||
op_cache: cache::Ops,
|
||||
val_cache: BTreeMap<String, Rc<Value>>,
|
||||
assert_results: AssertCollector,
|
||||
@ -37,28 +40,40 @@ pub struct Builtins {
|
||||
importer_registry: ImporterRegistry,
|
||||
working_dir: PathBuf,
|
||||
import_path: Vec<PathBuf>,
|
||||
// TODO(jwall): IO sink for stderr
|
||||
// TODO(jwall): IO sink for stdout
|
||||
stdout: Out,
|
||||
stderr: Err,
|
||||
}
|
||||
|
||||
impl Builtins {
|
||||
pub fn new() -> Self {
|
||||
Self::with_working_dir(std::env::current_dir().unwrap())
|
||||
type ByteSink = Vec<u8>;
|
||||
|
||||
impl<Out: Write, Err: Write> Builtins<Out, Err> {
|
||||
pub fn new(out: Out, err: Err) -> Self {
|
||||
Self::with_working_dir(std::env::current_dir().unwrap(), out, err)
|
||||
}
|
||||
|
||||
pub fn with_working_dir<P: Into<PathBuf>>(path: P) -> Self {
|
||||
pub fn with_working_dir<P: Into<PathBuf>>(path: P, out: Out, err: Err) -> Self {
|
||||
Self {
|
||||
op_cache: cache::Ops::new(),
|
||||
val_cache: BTreeMap::new(),
|
||||
assert_results: AssertCollector::new(),
|
||||
converter_registry: ConverterRegistry::make_registry(),
|
||||
importer_registry: ImporterRegistry::make_registry(),
|
||||
// TODO(jwall): This should move into the VM and not in the Runtime.
|
||||
// FIXME(jwall): This should move into the VM and not in the Runtime.
|
||||
working_dir: path.into(),
|
||||
import_path: Vec::new(),
|
||||
stdout: out,
|
||||
stderr: err,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_stdout(&self) -> &Out {
|
||||
&self.stdout
|
||||
}
|
||||
|
||||
pub fn get_stderr(&self) -> &Err {
|
||||
&self.stderr
|
||||
}
|
||||
|
||||
pub fn handle<P: AsRef<Path>>(
|
||||
&mut self,
|
||||
path: P,
|
||||
@ -76,6 +91,7 @@ impl Builtins {
|
||||
Hook::Reduce => self.reduce(path, stack),
|
||||
Hook::Regex => self.regex(stack),
|
||||
Hook::Range => self.range(stack),
|
||||
Hook::Trace(pos) => self.trace(stack, pos),
|
||||
}
|
||||
}
|
||||
|
||||
@ -488,4 +504,30 @@ impl Builtins {
|
||||
stack.push(Rc::new(C(List(elems))));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn trace(&mut self, mut stack: &mut Vec<Rc<Value>>, pos: Position) -> Result<(), Error> {
|
||||
let val = if let Some(val) = dbg!(stack.pop()) {
|
||||
val
|
||||
} else {
|
||||
return Err(dbg!(Error {}));
|
||||
};
|
||||
let expr = stack.pop();
|
||||
let expr_pretty = match expr {
|
||||
Some(ref expr) => match dbg!(expr.as_ref()) {
|
||||
&P(Str(ref expr)) => expr.clone(),
|
||||
_ => return Err(dbg!(Error {})),
|
||||
},
|
||||
_ => return Err(dbg!(Error {})),
|
||||
};
|
||||
let writable_val: Val = TryFrom::try_from(val.clone())?;
|
||||
if let Err(_) = writeln!(
|
||||
&mut self.stderr,
|
||||
"TRACE: {} = {} at {}",
|
||||
expr_pretty, writable_val, pos
|
||||
) {
|
||||
return Err(dbg!(Error {}));
|
||||
};
|
||||
stack.push(val);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
@ -754,3 +754,19 @@ fn simple_selects() {
|
||||
"select \"quux\", 3, { foo = 1, bar = 2, };" => P(Int(3)),
|
||||
];
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn simple_trace() {
|
||||
let stmts = parse(OffsetStrIter::from(dbg!("TRACE 1+1;")), None).unwrap();
|
||||
let ops = Rc::new(translate::AST::translate(stmts));
|
||||
assert!(ops.len() > 0);
|
||||
let mut vm = VM::new("foo.ucg", ops.clone());
|
||||
vm.run().unwrap();
|
||||
assert_eq!(vm.pop().unwrap(), Rc::new(P(Int(2))));
|
||||
let runtime = vm.get_runtime();
|
||||
let err_out = runtime.get_stderr();
|
||||
assert_eq!(
|
||||
String::from_utf8_lossy(err_out).to_owned(),
|
||||
"TRACE: 1 + 1 = 2 at line: 1 column: 1\n"
|
||||
);
|
||||
}
|
||||
|
@ -402,7 +402,15 @@ impl AST {
|
||||
ops.push(Op::Cp);
|
||||
}
|
||||
Expression::Debug(def) => {
|
||||
unimplemented!("Debug expressions are not implmented yet");
|
||||
let mut buffer: Vec<u8> = Vec::new();
|
||||
{
|
||||
let mut printer = crate::ast::printer::AstPrinter::new(2, &mut buffer);
|
||||
let _ = printer.render_expr(&def.expr);
|
||||
}
|
||||
let expr_pretty = String::from_utf8(buffer).unwrap();
|
||||
ops.push(Op::Val(Primitive::Str(expr_pretty)));
|
||||
Self::translate_expr(*def.expr, &mut ops);
|
||||
ops.push(Op::Runtime(Hook::Trace(def.pos)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -11,6 +11,7 @@
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
use std::cell::Ref;
|
||||
use std::cell::RefCell;
|
||||
use std::path::PathBuf;
|
||||
use std::rc::Rc;
|
||||
@ -28,7 +29,8 @@ use super::{Func, Module};
|
||||
pub struct VM {
|
||||
stack: Vec<Rc<Value>>,
|
||||
symbols: Stack,
|
||||
runtime: Rc<RefCell<runtime::Builtins>>,
|
||||
// FIXME(jwall): This should be parameterized.
|
||||
runtime: Rc<RefCell<runtime::Builtins<Vec<u8>, Vec<u8>>>>,
|
||||
ops: OpPointer,
|
||||
// TODO(jwall): This should be optional
|
||||
path: PathBuf,
|
||||
@ -43,12 +45,16 @@ impl<'a> VM {
|
||||
Self {
|
||||
stack: Vec::new(),
|
||||
symbols: Stack::new(),
|
||||
runtime: Rc::new(RefCell::new(runtime::Builtins::new())),
|
||||
runtime: Rc::new(RefCell::new(runtime::Builtins::new(Vec::new(), Vec::new()))),
|
||||
ops: ops,
|
||||
path: path.into(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_runtime(&self) -> Ref<runtime::Builtins<Vec<u8>, Vec<u8>>> {
|
||||
self.runtime.as_ref().borrow()
|
||||
}
|
||||
|
||||
pub fn to_scoped(self, symbols: Stack) -> Self {
|
||||
Self {
|
||||
stack: Vec::new(),
|
||||
|
Loading…
x
Reference in New Issue
Block a user