feat(tvix/eval): thread codemap through to disassembler

If the disassembler feature is enabled, make sure that an Rc of the
codemap is available through the chunk.

Change-Id: I700f27ab665a704f73457b19bd2d7efc93828a16
Reviewed-on: https://cl.tvl.fyi/c/depot/+/6414
Reviewed-by: sterni <sternenseemann@systemli.org>
Tested-by: BuildkiteCI
This commit is contained in:
Vincent Ambo 2022-09-02 17:44:31 +03:00 committed by tazjin
parent a3b19ad8be
commit cc526a2c87
4 changed files with 47 additions and 5 deletions

View file

@ -26,6 +26,9 @@ pub struct Chunk {
pub code: Vec<OpCode>, pub code: Vec<OpCode>,
pub constants: Vec<Value>, pub constants: Vec<Value>,
spans: Vec<SourceSpan>, spans: Vec<SourceSpan>,
#[cfg(feature = "disassembler")]
pub codemap: std::rc::Rc<codemap::CodeMap>,
} }
impl Chunk { impl Chunk {

View file

@ -55,10 +55,18 @@ impl LambdaCtx {
} }
fn inherit(&self) -> Self { fn inherit(&self) -> Self {
LambdaCtx { let ctx = LambdaCtx {
lambda: Lambda::new_anonymous(), lambda: Lambda::new_anonymous(),
scope: self.scope.inherit(), scope: self.scope.inherit(),
} };
#[cfg(feature = "disassembler")]
let ctx = (|mut c: Self| {
c.lambda.chunk.codemap = self.lambda.chunk.codemap.clone();
c
})(ctx);
ctx
} }
} }
@ -84,6 +92,12 @@ struct Compiler<'code> {
/// and is used to track the spans from which instructions where /// and is used to track the spans from which instructions where
/// derived. /// derived.
file: &'code codemap::File, file: &'code codemap::File,
#[cfg(feature = "disassembler")]
/// Carry a reference to the codemap around when the disassembler
/// is enabled, to allow displaying lines and other source
/// information in the disassembler output.
codemap: Rc<codemap::CodeMap>,
} }
// Helper functions for emitting code and metadata to the internal // Helper functions for emitting code and metadata to the internal
@ -1331,6 +1345,8 @@ pub fn compile<'code>(
location: Option<PathBuf>, location: Option<PathBuf>,
file: &'code codemap::File, file: &'code codemap::File,
globals: HashMap<&'static str, Value>, globals: HashMap<&'static str, Value>,
#[cfg(feature = "disassembler")] codemap: Rc<codemap::CodeMap>,
) -> EvalResult<CompilationOutput> { ) -> EvalResult<CompilationOutput> {
let mut root_dir = match location { let mut root_dir = match location {
Some(dir) => Ok(dir), Some(dir) => Ok(dir),
@ -1353,12 +1369,19 @@ pub fn compile<'code>(
let mut c = Compiler { let mut c = Compiler {
root_dir, root_dir,
file, file,
#[cfg(feature = "disassembler")]
codemap,
globals: prepare_globals(globals), globals: prepare_globals(globals),
contexts: vec![LambdaCtx::new()], contexts: vec![LambdaCtx::new()],
warnings: vec![], warnings: vec![],
errors: vec![], errors: vec![],
}; };
#[cfg(feature = "disassembler")]
{
c.context_mut().lambda.chunk.codemap = c.codemap.clone();
}
c.compile(None, expr.clone()); c.compile(None, expr.clone());
// The final operation of any top-level Nix program must always be // The final operation of any top-level Nix program must always be

View file

@ -5,7 +5,7 @@ use std::io::{Stderr, Write};
use tabwriter::TabWriter; use tabwriter::TabWriter;
use crate::chunk::Chunk; use crate::chunk::Chunk;
use crate::opcode::OpCode; use crate::opcode::{CodeIdx, OpCode};
use crate::value::Value; use crate::value::Value;
/// Helper struct to trace runtime values and automatically flush the /// Helper struct to trace runtime values and automatically flush the
@ -38,7 +38,16 @@ impl Drop for Tracer {
} }
fn disassemble_op(tw: &mut TabWriter<Stderr>, chunk: &Chunk, width: usize, offset: usize) { fn disassemble_op(tw: &mut TabWriter<Stderr>, chunk: &Chunk, width: usize, offset: usize) {
write!(tw, "{:0width$}\t ", width = width).ok(); write!(tw, "{:0width$}\t ", offset, width = width).ok();
let span = chunk.get_span(CodeIdx(offset));
if offset > 0 && chunk.get_span(CodeIdx(offset - 1)) == span {
write!(tw, " |\t").unwrap();
} else {
let loc = chunk.codemap.look_up_span(span);
write!(tw, "{:4}\t", loc.begin.line + 1).unwrap();
}
match chunk.code[offset] { match chunk.code[offset] {
OpCode::OpConstant(idx) => write!(tw, "OpConstant({})\n", chunk.constant(idx)).ok(), OpCode::OpConstant(idx) => write!(tw, "OpConstant({})\n", chunk.constant(idx)).ok(),

View file

@ -39,7 +39,14 @@ pub fn interpret(code: &str, location: Option<PathBuf>) -> EvalResult<Value> {
println!("{:?}", root_expr); println!("{:?}", root_expr);
} }
let result = crate::compiler::compile(root_expr, location, &file, global_builtins())?; let result = crate::compiler::compile(
root_expr,
location,
&file,
global_builtins(),
#[cfg(feature = "disassembler")]
std::rc::Rc::new(codemap),
)?;
#[cfg(feature = "disassembler")] #[cfg(feature = "disassembler")]
crate::disassembler::disassemble_chunk(&result.lambda.chunk); crate::disassembler::disassemble_chunk(&result.lambda.chunk);