Make SpanId and RegId also use new ID struct (#13963)

# Description
In the PR #13832 I used some newtypes for the old IDs. `SpanId` and
`RegId` already used newtypes, to streamline the code, I made them into
the same style as the other marker-based IDs.

Since `RegId` should be a bit smaller (it uses a `u32` instead of
`usize`) according to @devyn, I made the `Id` type generic with `usize`
as the default inner value.

The question still stands how `Display` should be implemented if even.

# User-Facing Changes
Users of the internal values of `RegId` or `SpanId` have breaking
changes but who outside nushell itself even uses these?

# After Submitting
The IDs will be streamlined and all type-safe.
This commit is contained in:
Piepmatz
2024-10-01 13:23:27 +02:00
committed by GitHub
parent 46589faaca
commit b2d0d9cf13
8 changed files with 66 additions and 41 deletions

View File

@ -58,9 +58,9 @@ impl BlockBuilder {
}
})
{
Ok(RegId(index as u32))
Ok(RegId::new(index as u32))
} else if self.register_allocation_state.len() < (u32::MAX as usize - 2) {
let reg_id = RegId(self.register_allocation_state.len() as u32);
let reg_id = RegId::new(self.register_allocation_state.len() as u32);
self.register_allocation_state.push(true);
Ok(reg_id)
} else {
@ -73,13 +73,16 @@ impl BlockBuilder {
/// Check if a register is initialized with a value.
pub(crate) fn is_allocated(&self, reg_id: RegId) -> bool {
self.register_allocation_state
.get(reg_id.0 as usize)
.get(reg_id.get() as usize)
.is_some_and(|state| *state)
}
/// Mark a register as initialized.
pub(crate) fn mark_register(&mut self, reg_id: RegId) -> Result<(), CompileError> {
if let Some(is_allocated) = self.register_allocation_state.get_mut(reg_id.0 as usize) {
if let Some(is_allocated) = self
.register_allocation_state
.get_mut(reg_id.get() as usize)
{
*is_allocated = true;
Ok(())
} else {
@ -92,7 +95,7 @@ impl BlockBuilder {
/// Mark a register as empty, so that it can be used again by something else.
#[track_caller]
pub(crate) fn free_register(&mut self, reg_id: RegId) -> Result<(), CompileError> {
let index = reg_id.0 as usize;
let index = reg_id.get() as usize;
if self
.register_allocation_state

View File

@ -18,7 +18,7 @@ use expression::compile_expression;
use operator::*;
use redirect::*;
const BLOCK_INPUT: RegId = RegId(0);
const BLOCK_INPUT: RegId = RegId::new(0);
/// Compile Nushell pipeline abstract syntax tree (AST) to internal representation (IR) instructions
/// for evaluation.

View File

@ -113,25 +113,28 @@ impl<'a> EvalContext<'a> {
#[inline]
fn put_reg(&mut self, reg_id: RegId, new_value: PipelineData) {
// log::trace!("{reg_id} <- {new_value:?}");
self.registers[reg_id.0 as usize] = new_value;
self.registers[reg_id.get() as usize] = new_value;
}
/// Borrow the contents of a register.
#[inline]
fn borrow_reg(&self, reg_id: RegId) -> &PipelineData {
&self.registers[reg_id.0 as usize]
&self.registers[reg_id.get() as usize]
}
/// Replace the contents of a register with `Empty` and then return the value that it contained
#[inline]
fn take_reg(&mut self, reg_id: RegId) -> PipelineData {
// log::trace!("<- {reg_id}");
std::mem::replace(&mut self.registers[reg_id.0 as usize], PipelineData::Empty)
std::mem::replace(
&mut self.registers[reg_id.get() as usize],
PipelineData::Empty,
)
}
/// Clone data from a register. Must be collected first.
fn clone_reg(&mut self, reg_id: RegId, error_span: Span) -> Result<PipelineData, ShellError> {
match &self.registers[reg_id.0 as usize] {
match &self.registers[reg_id.get() as usize] {
PipelineData::Empty => Ok(PipelineData::Empty),
PipelineData::Value(val, meta) => Ok(PipelineData::Value(val.clone(), meta.clone())),
_ => Err(ShellError::IrEvalError {