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:
parent
a3b19ad8be
commit
cc526a2c87
4 changed files with 47 additions and 5 deletions
|
@ -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 {
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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(),
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in a new issue