diff --git a/crates/rune/src/compile.rs b/crates/rune/src/compile.rs index 5efa21634..bf2170e89 100644 --- a/crates/rune/src/compile.rs +++ b/crates/rune/src/compile.rs @@ -34,8 +34,7 @@ mod prelude; pub(crate) use self::prelude::Prelude; pub(crate) mod ir; -pub use self::ir::IrValue; -pub(crate) use self::ir::{IrBudget, IrCompiler, IrEvalOutcome, IrInterpreter}; +pub(crate) use self::ir::{IrBudget, IrCompiler, IrEvalOutcome, IrInterpreter, IrValue}; pub use rune_core::{Component, ComponentRef, IntoComponent, Item, ItemBuf}; diff --git a/crates/rune/src/compile/error.rs b/crates/rune/src/compile/error.rs index 32df0a237..910c784c6 100644 --- a/crates/rune/src/compile/error.rs +++ b/crates/rune/src/compile/error.rs @@ -651,7 +651,6 @@ impl crate::no_std::error::Error for MissingScope {} pub(crate) enum PopError { MissingScope(usize), MissingParentScope(usize), - MissingVariable(usize), } impl fmt::Display for PopError { @@ -660,7 +659,6 @@ impl fmt::Display for PopError { match self { PopError::MissingScope(id) => write!(f, "Missing scope with id {id}"), PopError::MissingParentScope(id) => write!(f, "Missing parent scope with id {id}"), - PopError::MissingVariable(id) => write!(f, "Missing variable with id {id}"), } } } diff --git a/crates/rune/src/compile/ir.rs b/crates/rune/src/compile/ir.rs index de88c5535..651863a8f 100644 --- a/crates/rune/src/compile/ir.rs +++ b/crates/rune/src/compile/ir.rs @@ -13,7 +13,7 @@ mod interpreter; pub(crate) use self::interpreter::{IrBudget, IrInterpreter}; mod value; -pub use self::value::IrValue; +pub(crate) use self::value::IrValue; use core::ops::{AddAssign, MulAssign, ShlAssign, ShrAssign, SubAssign}; @@ -38,13 +38,13 @@ impl ast::Expr { let ir = { // TODO: avoid this arena? - let arena = crate::hir::Arena::new(); - let mut hir_ctx = crate::hir::lowering::Ctx::with_const( + let arena = hir::Arena::new(); + let mut hir_ctx = hir::lowering::Ctx::with_const( &arena, ctx.idx.q.borrow(), ctx.item_meta.location.source_id, ); - let hir = crate::hir::lowering::expr(&mut hir_ctx, &expr)?; + let hir = hir::lowering::expr(&mut hir_ctx, &expr)?; let mut c = IrCompiler { source_id: ctx.item_meta.location.source_id, @@ -90,7 +90,7 @@ macro_rules! decl_kind { /// A single operation in the Rune intermediate language. #[derive(Debug, Clone, Spanned)] -pub struct Ir { +pub(crate) struct Ir { #[rune(span)] pub(crate) span: Span, pub(crate) kind: IrKind, @@ -112,7 +112,7 @@ impl Ir { /// The target of a set operation. #[derive(Debug, Clone, Spanned)] -pub struct IrTarget { +pub(crate) struct IrTarget { /// Span of the target. #[rune(span)] pub(crate) span: Span, @@ -122,9 +122,9 @@ pub struct IrTarget { /// The kind of the target. #[derive(Debug, Clone)] -pub enum IrTargetKind { +pub(crate) enum IrTargetKind { /// A variable. - Name(Box), + Name(hir::OwnedName), /// A field target. Field(Box, Box), /// An index target. @@ -134,7 +134,7 @@ pub enum IrTargetKind { decl_kind! { /// The kind of an intermediate operation. #[derive(Debug, Clone)] - pub enum IrKind { + pub(crate) enum IrKind { /// Push a scope with the given instructions. Scope(IrScope), /// A binary operation. @@ -173,7 +173,7 @@ decl_kind! { /// An interpeted function. #[derive(Debug, Clone, Spanned)] -pub struct IrFn { +pub(crate) struct IrFn { /// The span of the function. #[rune(span)] pub(crate) span: Span, @@ -192,15 +192,15 @@ impl IrFn { for arg in hir.args { if let hir::FnArg::Pat(hir::Pat { - kind: hir::PatKind::Path(&hir::PatPathKind::Ident(ident, _)), + kind: hir::PatKind::Path(&hir::PatPathKind::Ident(name)), .. }) = arg { - args.push(ident.into()); + args.push(name.into()); continue; } - return Err(compile::Error::msg(arg, "unsupported argument in const fn")); + return Err(compile::Error::msg(arg, "Unsupported argument in const fn")); } let ir_scope = compiler::block(hir.body, c)?; @@ -215,7 +215,7 @@ impl IrFn { /// Definition of a new variable scope. #[derive(Debug, Clone, Spanned)] -pub struct IrScope { +pub(crate) struct IrScope { /// The span of the scope. #[rune(span)] pub(crate) span: Span, @@ -227,7 +227,7 @@ pub struct IrScope { /// A binary operation. #[derive(Debug, Clone, Spanned)] -pub struct IrBinary { +pub(crate) struct IrBinary { /// The span of the binary op. #[rune(span)] pub(crate) span: Span, @@ -241,7 +241,7 @@ pub struct IrBinary { /// A local variable declaration. #[derive(Debug, Clone, Spanned)] -pub struct IrDecl { +pub(crate) struct IrDecl { /// The span of the declaration. #[rune(span)] pub(crate) span: Span, @@ -253,7 +253,7 @@ pub struct IrDecl { /// Set a target. #[derive(Debug, Clone, Spanned)] -pub struct IrSet { +pub(crate) struct IrSet { /// The span of the set operation. #[rune(span)] pub(crate) span: Span, @@ -265,7 +265,7 @@ pub struct IrSet { /// Assign a target. #[derive(Debug, Clone, Spanned)] -pub struct IrAssign { +pub(crate) struct IrAssign { /// The span of the set operation. #[rune(span)] pub(crate) span: Span, @@ -279,7 +279,7 @@ pub struct IrAssign { /// A string template. #[derive(Debug, Clone, Spanned)] -pub struct IrTemplate { +pub(crate) struct IrTemplate { /// The span of the template. #[rune(span)] pub(crate) span: Span, @@ -289,7 +289,7 @@ pub struct IrTemplate { /// A string template. #[derive(Debug, Clone)] -pub enum IrTemplateComponent { +pub(crate) enum IrTemplateComponent { /// An ir expression. Ir(Ir), /// A literal string. @@ -298,10 +298,10 @@ pub enum IrTemplateComponent { /// Branch conditions in intermediate representation. #[derive(Debug, Clone, Spanned)] -pub struct IrBranches { +pub(crate) struct IrBranches { /// Span associated with branches. #[rune(span)] - pub span: Span, + pub(crate) span: Span, /// branches and their associated conditions. pub(crate) branches: Vec<(IrCondition, IrScope)>, /// The default fallback branch. @@ -310,7 +310,7 @@ pub struct IrBranches { /// The condition for a branch. #[derive(Debug, Clone, Spanned)] -pub enum IrCondition { +pub(crate) enum IrCondition { /// A simple conditional ir expression. Ir(Ir), /// A pattern match. @@ -319,7 +319,7 @@ pub enum IrCondition { /// A pattern match. #[derive(Debug, Clone, Spanned)] -pub struct IrLet { +pub(crate) struct IrLet { /// The span of the let condition. #[rune(span)] pub(crate) span: Span, @@ -331,7 +331,7 @@ pub struct IrLet { /// A pattern. #[derive(Debug, Clone)] -pub enum IrPat { +pub(crate) enum IrPat { /// An ignore pattern `_`. Ignore, /// A named binding. @@ -342,8 +342,8 @@ impl IrPat { fn compile_ast(hir: &hir::Pat<'_>) -> compile::Result { match hir.kind { hir::PatKind::Ignore => return Ok(ir::IrPat::Ignore), - hir::PatKind::Path(&hir::PatPathKind::Ident(ident, _)) => { - return Ok(ir::IrPat::Binding(ident.into())); + hir::PatKind::Path(&hir::PatPathKind::Ident(name)) => { + return Ok(ir::IrPat::Binding(name.into())); } _ => (), } @@ -372,7 +372,7 @@ impl IrPat { /// A loop with an optional condition. #[derive(Debug, Clone, Spanned)] -pub struct IrLoop { +pub(crate) struct IrLoop { /// The span of the loop. #[rune(span)] pub(crate) span: Span, @@ -386,7 +386,7 @@ pub struct IrLoop { /// A break operation. #[derive(Debug, Clone, Spanned)] -pub struct IrBreak { +pub(crate) struct IrBreak { /// The span of the break. #[rune(span)] pub(crate) span: Span, @@ -438,7 +438,7 @@ impl IrBreak { /// The kind of a break expression. #[derive(Debug, Clone)] -pub enum IrBreakKind { +pub(crate) enum IrBreakKind { /// Break to the next loop. Inherent, /// Break to the given label. @@ -449,7 +449,7 @@ pub enum IrBreakKind { /// Tuple expression. #[derive(Debug, Clone, Spanned)] -pub struct IrTuple { +pub(crate) struct IrTuple { /// Span of the tuple. #[rune(span)] pub(crate) span: Span, @@ -459,7 +459,7 @@ pub struct IrTuple { /// Object expression. #[derive(Debug, Clone, Spanned)] -pub struct IrObject { +pub(crate) struct IrObject { /// Span of the object. #[rune(span)] pub(crate) span: Span, @@ -469,7 +469,7 @@ pub struct IrObject { /// Call expressions. #[derive(Debug, Clone, Spanned)] -pub struct IrCall { +pub(crate) struct IrCall { /// Span of the call. #[rune(span)] pub(crate) span: Span, @@ -481,7 +481,7 @@ pub struct IrCall { /// Vector expression. #[derive(Debug, Clone, Spanned)] -pub struct IrVec { +pub(crate) struct IrVec { /// Span of the vector. #[rune(span)] pub(crate) span: Span, @@ -491,7 +491,7 @@ pub struct IrVec { /// A binary operation. #[derive(Debug, Clone, Copy)] -pub enum IrBinaryOp { +pub(crate) enum IrBinaryOp { /// Add `+`. Add, /// Subtract `-`. @@ -518,7 +518,7 @@ pub enum IrBinaryOp { /// An assign operation. #[derive(Debug, Clone, Copy)] -pub enum IrAssignOp { +pub(crate) enum IrAssignOp { /// `+=`. Add, /// `-=`. diff --git a/crates/rune/src/compile/ir/compiler.rs b/crates/rune/src/compile/ir/compiler.rs index 96abbafbe..212bcdc88 100644 --- a/crates/rune/src/compile/ir/compiler.rs +++ b/crates/rune/src/compile/ir/compiler.rs @@ -33,10 +33,10 @@ impl IrCompiler<'_> { /// Resolve an ir target from an expression. fn ir_target(&self, expr: &hir::Expr<'_>) -> compile::Result { match expr.kind { - hir::ExprKind::Variable(_, name) => { + hir::ExprKind::Variable(name) => { return Ok(ir::IrTarget { span: expr.span(), - kind: ir::IrTargetKind::Name(name.into()), + kind: ir::IrTargetKind::Name(name.into_owned()), }); } hir::ExprKind::FieldAccess(expr_field_access) => { @@ -102,8 +102,8 @@ pub(crate) fn expr(hir: &hir::Expr<'_>, c: &mut IrCompiler<'_>) -> compile::Resu ir::Ir::new(span, ir::IrValue::from_const(value)) } - hir::ExprKind::Variable(_, name) => { - return Ok(ir::Ir::new(span, >::from(name))); + hir::ExprKind::Variable(name) => { + return Ok(ir::Ir::new(span, >::from(name.as_str()))); } _ => { return Err(compile::Error::msg( @@ -378,7 +378,7 @@ fn local(hir: &hir::Local<'_>, c: &mut IrCompiler<'_>) -> compile::Result { return expr(hir.expr, c); } - hir::PatKind::Path(&hir::PatPathKind::Ident(ident, _)) => ident, + hir::PatKind::Path(&hir::PatPathKind::Ident(name)) => name, _ => { return Err(compile::Error::msg(span, "not supported yet")); } diff --git a/crates/rune/src/compile/ir/interpreter.rs b/crates/rune/src/compile/ir/interpreter.rs index 8afe09f99..df4fc53d0 100644 --- a/crates/rune/src/compile/ir/interpreter.rs +++ b/crates/rune/src/compile/ir/interpreter.rs @@ -183,7 +183,9 @@ impl IrScopes { /// Get the given target as mut. pub(crate) fn get_target(&mut self, ir_target: &ir::IrTarget) -> compile::Result { match &ir_target.kind { - ir::IrTargetKind::Name(name) => Ok(self.get_name(name).with_span(ir_target)?.clone()), + ir::IrTargetKind::Name(name) => { + Ok(self.get_name(name.as_str()).with_span(ir_target)?.clone()) + } ir::IrTargetKind::Field(ir_target, field) => { let value = self.get_target(ir_target)?; @@ -250,7 +252,7 @@ impl IrScopes { ) -> compile::Result<()> { match &ir_target.kind { ir::IrTargetKind::Name(name) => { - *self.get_name_mut(name.as_ref()).with_span(ir_target)? = value; + *self.get_name_mut(name.as_str()).with_span(ir_target)? = value; Ok(()) } ir::IrTargetKind::Field(target, field) => { @@ -310,7 +312,7 @@ impl IrScopes { ) -> compile::Result<()> { match &ir_target.kind { ir::IrTargetKind::Name(name) => { - let value = self.get_name_mut(name.as_ref()).with_span(ir_target)?; + let value = self.get_name_mut(name.as_str()).with_span(ir_target)?; op(value) } ir::IrTargetKind::Field(target, field) => { diff --git a/crates/rune/src/compile/v1/assemble.rs b/crates/rune/src/compile/v1/assemble.rs index bc74ee59b..33916382c 100644 --- a/crates/rune/src/compile/v1/assemble.rs +++ b/crates/rune/src/compile/v1/assemble.rs @@ -84,7 +84,7 @@ pub(crate) fn fn_from_item_fn<'hir>( for arg in hir.args { match arg { - hir::FnArg::SelfValue(span, variable) => { + hir::FnArg::SelfValue(span) => { if !instance_fn || !first { return Err(compile::Error::new( *span, @@ -92,7 +92,7 @@ pub(crate) fn fn_from_item_fn<'hir>( )); } - c.scopes.define(*variable, hir::Name::SelfValue, span)?; + c.scopes.define(hir::Name::SelfValue, span)?; } hir::FnArg::Pat(pat) => { let offset = c.scopes.alloc(pat)?; @@ -134,8 +134,8 @@ pub(crate) fn async_block_secondary<'hir>( c: &mut Assembler<'_, 'hir>, hir: &'hir hir::AsyncBlock<'hir>, ) -> compile::Result<()> { - for (variable, capture) in hir.captures.iter().copied() { - c.scopes.define(variable, capture, &hir.block)?; + for name in hir.captures.iter().copied() { + c.scopes.define(name, &hir.block)?; } return_(c, &hir.block, hir.block, block)?; @@ -167,8 +167,8 @@ pub(crate) fn expr_closure_secondary<'hir>( if !hir.captures.is_empty() { c.asm.push(Inst::PushTuple, span); - for (variable, capture) in hir.captures.iter().copied() { - c.scopes.define(variable, capture, span)?; + for capture in hir.captures.iter().copied() { + c.scopes.define(capture, span)?; } } @@ -269,9 +269,9 @@ fn pat<'hir>( .pop_and_jump_if_not(c.scopes.local(hir)?, false_label, hir); Ok(true) } - hir::PatPathKind::Ident(name, variable) => { + hir::PatPathKind::Ident(name) => { load(c, Needs::Value)?; - c.scopes.define(variable, name.into(), hir)?; + c.scopes.define(hir::Name::Str(name), hir)?; Ok(false) } }, @@ -559,9 +559,9 @@ fn pat_object<'hir>( pat(c, p, false_label, &load)?; } - hir::Binding::Ident(span, name, variable) => { + hir::Binding::Ident(span, name) => { c.asm.push(Inst::ObjectIndexGetAt { offset, slot }, &span); - c.scopes.define(variable, name.into(), binding)?; + c.scopes.define(hir::Name::Str(name), binding)?; } } } @@ -848,19 +848,8 @@ fn expr<'hir>( let span = hir; let asm = match hir.kind { - hir::ExprKind::SelfValue(variable) => { - let var = c - .scopes - .get(&mut c.q, variable, hir::Name::SelfValue, span)?; - - if needs.value() { - var.copy(c, span, hir::Name::SelfValue); - } - - Asm::top(span) - } - hir::ExprKind::Variable(variable, name) => { - let var = c.scopes.get(&mut c.q, variable, name.into(), span)?; + hir::ExprKind::Variable(name) => { + let var = c.scopes.get(&mut c.q, name, span)?; Asm::var(span, var) } hir::ExprKind::Type(ty) => { @@ -927,9 +916,9 @@ fn expr_assign<'hir>( ) -> compile::Result> { let supported = match hir.lhs.kind { // = - hir::ExprKind::Variable(variable, name) => { + hir::ExprKind::Variable(name) => { expr(c, hir.rhs, Needs::Value)?.apply(c)?; - let var = c.scopes.get(&mut c.q, variable, name.into(), span)?; + let var = c.scopes.get(&mut c.q, name, span)?; c.asm.push_with_comment( Inst::Replace { offset: var.offset }, span, @@ -1152,9 +1141,9 @@ fn expr_binary<'hir>( ) -> compile::Result<()> { let supported = match lhs.kind { // - hir::ExprKind::Variable(variable, name) => { + hir::ExprKind::Variable(name) => { expr(c, rhs, Needs::Value)?.apply(c)?; - let var = c.scopes.get(&mut c.q, variable, name.into(), lhs)?; + let var = c.scopes.get(&mut c.q, name, lhs)?; Some(InstTarget::Offset(var.offset)) } // . @@ -1235,12 +1224,12 @@ fn expr_async_block<'hir>( span: &'hir dyn Spanned, needs: Needs, ) -> compile::Result> { - for (variable, capture) in hir.captures.iter().copied() { + for capture in hir.captures.iter().copied() { if hir.do_move { - let var = c.scopes.take(&mut c.q, variable, capture, span)?; + let var = c.scopes.take(&mut c.q, capture, span)?; var.do_move(c.asm, span, "capture"); } else { - let var = c.scopes.get(&mut c.q, variable, capture, span)?; + let var = c.scopes.get(&mut c.q, capture, span)?; var.copy(c, span, "capture"); } } @@ -1354,8 +1343,8 @@ fn expr_call<'hir>( let args = hir.args.len(); match hir.call { - hir::Call::Var { name, variable, .. } => { - let var = c.scopes.get(&mut c.q, variable, name.into(), span)?; + hir::Call::Var { name, .. } => { + let var = c.scopes.get(&mut c.q, name, span)?; for e in hir.args { expr(c, e, Needs::Value)?.apply(c)?; @@ -1434,12 +1423,12 @@ fn expr_call_closure<'hir>( tracing::trace!(?hir.captures, "assemble call closure"); // Construct a closure environment. - for (variable, capture) in hir.captures.iter().copied() { + for capture in hir.captures.iter().copied() { if hir.do_move { - let var = c.scopes.take(&mut c.q, variable, capture, span)?; + let var = c.scopes.take(&mut c.q, capture, span)?; var.do_move(c.asm, span, "capture"); } else { - let var = c.scopes.get(&mut c.q, variable, capture, span)?; + let var = c.scopes.get(&mut c.q, capture, span)?; var.copy(c, span, "capture"); } } @@ -1505,8 +1494,8 @@ fn expr_field_access<'hir>( // climbing the hir like we do here. #[allow(clippy::single_match)] match (hir.expr.kind, hir.expr_field) { - (hir::ExprKind::Variable(variable, name), hir::ExprField::LitNumber(n)) => { - if try_immediate_field_access_optimization(c, variable, name, n, span, needs)? { + (hir::ExprKind::Variable(name), hir::ExprField::LitNumber(n)) => { + if try_immediate_field_access_optimization(c, name, n, span, needs)? { return Ok(Asm::top(span)); } } @@ -1549,8 +1538,7 @@ fn expr_field_access<'hir>( fn try_immediate_field_access_optimization<'hir>( c: &mut Assembler<'_, 'hir>, - variable: hir::Variable, - name: &'hir str, + name: hir::Name<'hir>, n: &ast::LitNumber, span: &dyn Spanned, needs: Needs, @@ -1563,7 +1551,7 @@ fn expr_field_access<'hir>( return Ok(false); }; - let var = c.scopes.get(&mut c.q, variable, name.into(), span)?; + let var = c.scopes.get(&mut c.q, name, span)?; c.asm.push_with_comment( Inst::TupleIndexGetAt { @@ -2166,8 +2154,8 @@ fn expr_select<'hir>( let expected = c.scopes.child(span)?; match branch.pat.kind { - hir::PatKind::Path(&hir::PatPathKind::Ident(name, variable)) => { - c.scopes.define(variable, name.into(), branch.pat)?; + hir::PatKind::Path(&hir::PatPathKind::Ident(name)) => { + c.scopes.define(hir::Name::Str(name), branch.pat)?; } hir::PatKind::Ignore => { c.asm.push(Inst::Pop, span); diff --git a/crates/rune/src/compile/v1/scopes.rs b/crates/rune/src/compile/v1/scopes.rs index e8eeaec97..79c4b6a23 100644 --- a/crates/rune/src/compile/v1/scopes.rs +++ b/crates/rune/src/compile/v1/scopes.rs @@ -129,7 +129,6 @@ impl<'hir> Scopes<'hir> { pub(crate) fn get( &self, q: &mut Query<'_>, - variable: hir::Variable, name: hir::Name<'hir>, span: &'hir dyn Spanned, ) -> compile::Result> { @@ -137,7 +136,7 @@ impl<'hir> Scopes<'hir> { for layer in self.layers.iter().rev() { if let Some(var) = layer.variables.get(&name) { - tracing::trace!(?variable, ?var, "getting var"); + tracing::trace!(?var, "getting var"); q.visitor.visit_variable_use(self.source_id, var.span, span); if let Some(moved_at) = var.moved_at { @@ -155,7 +154,7 @@ impl<'hir> Scopes<'hir> { Err(compile::Error::msg( span, - format_args!("Missing variable `{name}` ({variable})"), + format_args!("Missing variable `{name}`"), )) } @@ -164,7 +163,6 @@ impl<'hir> Scopes<'hir> { pub(crate) fn take( &mut self, q: &mut Query<'_>, - variable: hir::Variable, name: hir::Name<'hir>, span: &'hir dyn Spanned, ) -> compile::Result<&Var> { @@ -172,7 +170,7 @@ impl<'hir> Scopes<'hir> { for layer in self.layers.iter_mut().rev() { if let Some(var) = layer.variables.get_mut(&name) { - tracing::trace!(?variable, ?var, "taking var"); + tracing::trace!(?var, "taking var"); q.visitor.visit_variable_use(self.source_id, var.span, span); if let Some(moved_at) = var.moved_at { @@ -191,7 +189,7 @@ impl<'hir> Scopes<'hir> { Err(compile::Error::msg( span, - format_args!("Missing variable `{name}` to take ({variable})"), + format_args!("Missing variable `{name}` to take"), )) } @@ -199,7 +197,6 @@ impl<'hir> Scopes<'hir> { #[tracing::instrument(skip_all, fields(variable, name))] pub(crate) fn define( &mut self, - #[allow(unused)] variable: hir::Variable, name: hir::Name<'hir>, span: &'hir dyn Spanned, ) -> compile::Result { diff --git a/crates/rune/src/hir.rs b/crates/rune/src/hir.rs index beb209eaf..ba3869482 100644 --- a/crates/rune/src/hir.rs +++ b/crates/rune/src/hir.rs @@ -7,4 +7,4 @@ pub(crate) use self::hir::*; pub(crate) mod lowering; pub(crate) mod scopes; -pub(crate) use self::scopes::{Name, OwnedCapture, Scopes, Variable}; +pub(crate) use self::scopes::{Name, OwnedName, Scopes}; diff --git a/crates/rune/src/hir/hir.rs b/crates/rune/src/hir/hir.rs index 15dc304b2..95429aef4 100644 --- a/crates/rune/src/hir/hir.rs +++ b/crates/rune/src/hir/hir.rs @@ -2,7 +2,7 @@ use core::num::NonZeroUsize; use crate as rune; use crate::ast::{self, Span, Spanned}; -use crate::hir::{Name, Variable}; +use crate::hir::Name; use crate::parse::{Expectation, Id, IntoExpectation, NonZeroId, Opaque}; use crate::runtime::{format, Type, TypeCheck}; use crate::Hash; @@ -21,7 +21,7 @@ pub(crate) struct Pat<'hir> { #[derive(Debug, Clone, Copy)] pub(crate) enum PatPathKind<'hir> { Kind(&'hir PatItemsKind), - Ident(&'hir str, Variable), + Ident(&'hir str), } /// The kind of a [Pat]. @@ -84,23 +84,23 @@ pub(crate) struct PatItems<'hir> { #[non_exhaustive] pub(crate) enum Binding<'hir> { Binding(Span, &'hir str, &'hir Pat<'hir>), - Ident(Span, &'hir str, Variable), + Ident(Span, &'hir str), } impl<'hir> Spanned for Binding<'hir> { fn span(&self) -> Span { match self { Binding::Binding(span, _, _) => *span, - Binding::Ident(span, _, _) => *span, + Binding::Ident(span, _) => *span, } } } -impl Binding<'_> { - pub(crate) fn key(&self) -> &str { - match self { +impl<'hir> Binding<'hir> { + pub(crate) fn key(&self) -> &'hir str { + match *self { Self::Binding(_, key, _) => key, - Self::Ident(_, key, _) => key, + Self::Ident(_, key) => key, } } } @@ -133,8 +133,7 @@ pub(crate) enum Lit<'hir> { #[derive(Debug, Clone, Copy)] #[non_exhaustive] pub(crate) enum ExprKind<'hir> { - SelfValue(Variable), - Variable(Variable, &'hir str), + Variable(Name<'hir>), Type(Type), Fn(Hash), Path(&'hir Path<'hir>), @@ -225,7 +224,7 @@ pub(crate) struct ExprLoop<'hir> { pub(crate) body: &'hir Block<'hir>, /// Variables that have been defined by the loop header. #[allow(unused)] - pub(crate) drop: &'hir [Variable], + pub(crate) drop: &'hir [Name<'hir>], } /// A `for` loop over an iterator: `for i in [1, 2, 3] {}`. @@ -243,7 +242,7 @@ pub(crate) struct ExprFor<'hir> { pub(crate) body: &'hir Block<'hir>, /// Variables that have been defined by the loop header. #[allow(unused)] - pub(crate) drop: &'hir [Variable], + pub(crate) drop: &'hir [Name<'hir>], } /// A let expression `let = ` @@ -284,7 +283,7 @@ pub(crate) struct ConditionalBranch<'hir> { pub(crate) block: &'hir Block<'hir>, /// Variables that have been defined by the conditional header. #[allow(unused)] - pub(crate) drop: &'hir [Variable], + pub(crate) drop: &'hir [Name<'hir>], } /// A match expression. @@ -313,17 +312,14 @@ pub(crate) struct ExprMatchBranch<'hir> { /// Variables that have been defined by this match branch, which needs to be /// dropped. #[allow(unused)] - pub(crate) drop: &'hir [Variable], + pub(crate) drop: &'hir [Name<'hir>], } #[derive(Debug, Clone, Copy)] pub(crate) enum Call<'hir> { Var { /// The name of the variable being called. - name: &'hir str, - /// The variable that was looked up. - #[allow(unused)] - variable: Variable, + name: Name<'hir>, }, Instance { /// The target expression being called. @@ -424,7 +420,7 @@ pub(crate) enum ExprBreakValue<'hir> { pub(crate) struct ExprAsyncBlock<'hir> { pub(crate) hash: Hash, pub(crate) do_move: bool, - pub(crate) captures: &'hir [(Variable, Name<'hir>)], + pub(crate) captures: &'hir [Name<'hir>], } /// A `select` expression that selects over a collection of futures. @@ -457,7 +453,7 @@ pub(crate) struct ExprSelectPatBranch<'hir> { pub(crate) body: &'hir Expr<'hir>, /// Variables that need to be dropped by the end of this block. #[allow(unused)] - pub(crate) drop: &'hir [Variable], + pub(crate) drop: &'hir [Name<'hir>], } /// Calling a closure. @@ -466,7 +462,7 @@ pub(crate) struct ExprSelectPatBranch<'hir> { pub(crate) struct ExprCallClosure<'hir> { pub(crate) do_move: bool, pub(crate) hash: Hash, - pub(crate) captures: &'hir [(Variable, Name<'hir>)], + pub(crate) captures: &'hir [Name<'hir>], } /// A closure expression. @@ -481,7 +477,7 @@ pub(crate) struct ExprClosure<'hir> { /// The body of the closure. pub(crate) body: &'hir Expr<'hir>, /// Captures in the closure. - pub(crate) captures: &'hir [(Variable, Name<'hir>)], + pub(crate) captures: &'hir [Name<'hir>], } #[derive(Debug, Clone, Copy)] @@ -675,24 +671,15 @@ pub(crate) struct ItemFn<'hir> { } /// A single argument to a function. -#[derive(Debug, Clone, Copy)] +#[derive(Debug, Clone, Copy, Spanned)] #[non_exhaustive] pub(crate) enum FnArg<'hir> { /// The `self` parameter. - SelfValue(Span, Variable), + SelfValue(Span), /// Function argument is a pattern binding. Pat(&'hir Pat<'hir>), } -impl Spanned for FnArg<'_> { - fn span(&self) -> Span { - match self { - FnArg::SelfValue(span, _) => *span, - FnArg::Pat(pat) => pat.span(), - } - } -} - /// A block of statements. #[derive(Debug, Clone, Copy, Opaque, Spanned)] #[non_exhaustive] @@ -707,7 +694,7 @@ pub(crate) struct Block<'hir> { pub(crate) statements: &'hir [Stmt<'hir>], /// Variables that need to be dropped by the end of this block. #[allow(unused)] - pub(crate) drop: &'hir [Variable], + pub(crate) drop: &'hir [Name<'hir>], } impl Block<'_> { @@ -722,7 +709,7 @@ impl Block<'_> { #[derive(Debug, Clone, Copy)] pub(crate) struct AsyncBlock<'hir> { pub(crate) block: &'hir Block<'hir>, - pub(crate) captures: &'hir [(Variable, Name<'hir>)], + pub(crate) captures: &'hir [Name<'hir>], } /// A statement within a block. diff --git a/crates/rune/src/hir/lowering.rs b/crates/rune/src/hir/lowering.rs index 4ae05e095..66a31d845 100644 --- a/crates/rune/src/hir/lowering.rs +++ b/crates/rune/src/hir/lowering.rs @@ -252,16 +252,12 @@ pub(crate) fn async_block_secondary<'hir>( return Err(compile::Error::msg(ast, format_args!("Missing captures for hash {captures}"))); }; - let captures = &*iter!(captures, |(_, capture)| { + let captures = &*iter!(captures, |capture| { match capture { - hir::OwnedCapture::SelfValue => { - let variable = ctx.scopes.define_self().with_span(ast)?; - (variable, hir::Name::SelfValue) - } - hir::OwnedCapture::Name(name) => { + hir::OwnedName::SelfValue => ctx.scopes.define(hir::Name::SelfValue).with_span(ast)?, + hir::OwnedName::Str(name) => { let name = alloc_str!(name.as_str()); - let variable = ctx.scopes.define(name).with_span(ast)?; - (variable, hir::Name::Str(name)) + ctx.scopes.define(hir::Name::Str(name)).with_span(ast)? } } }); @@ -287,17 +283,15 @@ pub(crate) fn expr_closure_secondary<'hir>( return Err(compile::Error::msg(ast, format_args!("Missing captures for hash {captures}"))); }; - let captures = &*iter!(captures, |(_, capture)| (match capture { - hir::OwnedCapture::SelfValue => { - let variable = ctx.scopes.define_self().with_span(ast)?; - (variable, hir::Name::SelfValue) + let captures = &*iter!(captures, |capture| match capture { + hir::OwnedName::SelfValue => { + ctx.scopes.define(hir::Name::SelfValue).with_span(ast)? } - hir::OwnedCapture::Name(name) => { - let name = alloc_str!(name.as_str()); - let variable = ctx.scopes.define(name).with_span(ast)?; - (variable, hir::Name::Str(name)) + hir::OwnedName::Str(name) => { + let name = hir::Name::Str(alloc_str!(name.as_str())); + ctx.scopes.define(name).with_span(ast)? } - })); + }); let args = iter!(ast.args.as_slice(), |(ast, _)| fn_arg(ctx, ast)?); let body = alloc!(expr(ctx, &ast.body)?); @@ -367,13 +361,9 @@ fn expr_call_closure<'hir>( iter!(layer.captures()) } Some(captures) => { - iter!(captures, |&(variable, ref capture)| { - let capture = match capture { - hir::OwnedCapture::SelfValue => hir::Name::SelfValue, - hir::OwnedCapture::Name(name) => hir::Name::Str(alloc_str!(name.as_str())), - }; - - (variable, capture) + iter!(captures, |capture| match capture { + hir::OwnedName::SelfValue => hir::Name::SelfValue, + hir::OwnedName::Str(name) => hir::Name::Str(alloc_str!(name.as_str())), }) } }; @@ -438,7 +428,7 @@ pub(crate) fn expr_object<'hir>( let assign = match &ast.assign { Some((_, ast)) => alloc!(expr(ctx, ast)?), None => { - let Some(variable) = ctx.scopes.get(key.1) else { + let Some((name, _)) = ctx.scopes.get(hir::Name::Str(key.1)) else { return Err(compile::Error::new(key.0, CompileErrorKind::MissingLocal { name: key.1.to_owned(), },)) @@ -446,7 +436,7 @@ pub(crate) fn expr_object<'hir>( alloc!(hir::Expr { span: ast.span(), - kind: hir::ExprKind::Variable(variable, key.1) + kind: hir::ExprKind::Variable(name) }) } }; @@ -965,15 +955,9 @@ pub(crate) fn expr_block<'hir>( iter!(layer.captures()) } Some(captures) => { - iter!(captures, |&(variable, ref capture)| { - let capture = match capture { - hir::OwnedCapture::SelfValue => hir::Name::SelfValue, - hir::OwnedCapture::Name(name) => { - hir::Name::Str(alloc_str!(name.as_str())) - } - }; - - (variable, capture) + iter!(captures, |capture| match capture { + hir::OwnedName::SelfValue => hir::Name::SelfValue, + hir::OwnedName::Str(name) => hir::Name::Str(alloc_str!(name.as_str())), }) } }; @@ -999,8 +983,8 @@ fn fn_arg<'hir>(ctx: &mut Ctx<'hir, '_>, ast: &ast::FnArg) -> compile::Result { - let variable = ctx.scopes.define_self().with_span(ast)?; - hir::FnArg::SelfValue(ast.span(), variable) + ctx.scopes.define(hir::Name::SelfValue).with_span(ast)?; + hir::FnArg::SelfValue(ast.span()) } ast::FnArg::Pat(ast) => hir::FnArg::Pat(alloc!(pat(ctx, ast)?)), }) @@ -1053,9 +1037,9 @@ fn pat<'hir>(ctx: &mut Ctx<'hir, '_>, ast: &ast::Pat) -> compile::Result(ctx: &mut Ctx<'hir, '_>, ast: &ast::Pat) -> compile::Result { return Err(compile::Error::new( @@ -1287,22 +1271,22 @@ pub(crate) fn expr_path<'hir>( alloc_with!(ctx, ast); if let Some(ast::PathKind::SelfValue) = ast.as_kind() { - let Some(variable) = ctx.scopes.get_self() else { + let Some(..) = ctx.scopes.get(hir::Name::SelfValue) else { return Err(compile::Error::new( ast, CompileErrorKind::MissingSelf, )); }; - return Ok(hir::ExprKind::SelfValue(variable)); + return Ok(hir::ExprKind::Variable(hir::Name::SelfValue)); } if let Needs::Value = ctx.needs.get() { if let Some(name) = ast.try_as_ident() { let name = alloc_str!(name.resolve(resolve_context!(ctx.q))?); - if let Some(variable) = ctx.scopes.get(name) { - return Ok(hir::ExprKind::Variable(variable, alloc_str!(name))); + if let Some((name, _)) = ctx.scopes.get(hir::Name::Str(name)) { + return Ok(hir::ExprKind::Variable(name)); } } } @@ -1620,8 +1604,8 @@ fn expr_call<'hir>( if let Some(name) = path.try_as_ident() { let name = alloc_str!(name.resolve(resolve_context!(ctx.q))?); - if let Some(variable) = ctx.scopes.get(name) { - break 'ok hir::Call::Var { name, variable }; + if let Some((name, _)) = ctx.scopes.get(hir::Name::Str(name)) { + break 'ok hir::Call::Var { name }; } } diff --git a/crates/rune/src/hir/scopes.rs b/crates/rune/src/hir/scopes.rs index 1608408a8..85a5a25ec 100644 --- a/crates/rune/src/hir/scopes.rs +++ b/crates/rune/src/hir/scopes.rs @@ -4,8 +4,7 @@ use core::cell::RefCell; use core::fmt; use core::num::NonZeroUsize; -use crate::no_std::collections::BTreeSet; -use crate::no_std::collections::HashMap; +use crate::no_std::collections::{BTreeSet, HashSet}; use crate::no_std::prelude::*; use crate::no_std::vec::Vec; @@ -17,17 +16,6 @@ use rune_macros::instrument; #[repr(transparent)] pub(crate) struct Scope(usize); -#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] -#[repr(transparent)] -pub(crate) struct Variable(pub(crate) usize); - -impl fmt::Display for Variable { - #[inline] - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - self.0.fmt(f) - } -} - /// The kind of a layer. #[derive(Default)] enum LayerKind { @@ -38,9 +26,18 @@ enum LayerKind { /// An owned capture. #[derive(Debug, Clone)] -pub(crate) enum OwnedCapture { +pub(crate) enum OwnedName { SelfValue, - Name(String), + Str(String), +} + +impl OwnedName { + pub(crate) fn as_str(&self) -> &str { + match self { + OwnedName::SelfValue => "self", + OwnedName::Str(name) => name, + } + } } /// A captured variable. @@ -64,6 +61,14 @@ impl<'hir> Name<'hir> { pub(crate) fn into_string(self) -> String { String::from(self.as_str()) } + + /// Coerce into an owned name. + pub(crate) fn into_owned(self) -> OwnedName { + match self { + Name::SelfValue => OwnedName::SelfValue, + Name::Str(name) => OwnedName::Str(name.to_owned()), + } + } } impl<'hir> fmt::Display for Name<'hir> { @@ -73,26 +78,20 @@ impl<'hir> fmt::Display for Name<'hir> { } } -impl<'hir> From<&'hir str> for Name<'hir> { - #[inline] - fn from(string: &'hir str) -> Self { - Name::Str(string) - } -} - #[derive(Default)] pub(crate) struct Layer<'hir> { + /// Scope identifier of the layer. scope: Scope, + /// The parent layer. parent: Option, - /// Indicates if `self` is defined in this layer. - has_self: Option, + /// The kind of the layer. + kind: LayerKind, /// Variables defined in this layer. - variables: HashMap<&'hir str, usize>, + variables: HashSet>, /// Order of variable definitions. - order: Vec, - kind: LayerKind, + order: Vec>, /// Captures inside of this layer. - captures: BTreeSet<(Variable, Name<'hir>)>, + captures: BTreeSet>, } impl<'hir> Layer<'hir> { @@ -102,12 +101,12 @@ impl<'hir> Layer<'hir> { /// Convert layer into variable drop order. #[inline(always)] - pub(crate) fn into_drop_order(self) -> impl ExactSizeIterator { - self.order.into_iter().rev().map(Variable) + pub(crate) fn into_drop_order(self) -> impl ExactSizeIterator> { + self.order.into_iter().rev() } /// Variables captured by the layer. - pub(crate) fn captures(&self) -> impl ExactSizeIterator)> + '_ { + pub(crate) fn captures(&self) -> impl ExactSizeIterator> + '_ { self.captures.iter().copied() } } @@ -115,7 +114,6 @@ impl<'hir> Layer<'hir> { pub(crate) struct Scopes<'hir> { scope: Scope, scopes: slab::Slab>, - variables: slab::Slab<()>, } impl<'hir> Scopes<'hir> { @@ -129,8 +127,7 @@ impl<'hir> Scopes<'hir> { let layer = Layer { scope, parent: Some(NonZeroUsize::new(self.scope.0.wrapping_add(1)).expect("ran out of ids")), - has_self: None, - variables: HashMap::new(), + variables: HashSet::new(), order: Vec::new(), kind: LayerKind::Default, captures: BTreeSet::new(), @@ -147,8 +144,7 @@ impl<'hir> Scopes<'hir> { let layer = Layer { scope, parent: Some(NonZeroUsize::new(self.scope.0.wrapping_add(1)).expect("ran out of ids")), - has_self: None, - variables: HashMap::new(), + variables: HashSet::new(), order: Vec::new(), kind: LayerKind::Captures, captures: BTreeSet::new(), @@ -159,6 +155,7 @@ impl<'hir> Scopes<'hir> { } /// Pop the given scope. + #[tracing::instrument(skip_all, fields(?self.scope))] pub(crate) fn pop(&mut self) -> Result, PopError> { let Some(layer) = self.scopes.try_remove(self.scope.0) else { return Err(PopError::MissingScope(self.scope.0)); @@ -168,94 +165,60 @@ impl<'hir> Scopes<'hir> { return Err(PopError::MissingParentScope(self.scope.0)); }; - for &variable in &layer.order { - if self.variables.try_remove(variable).is_none() { - return Err(PopError::MissingVariable(variable)); - } - } - - self.scope = Scope(parent); + let to = Scope(parent); + tracing::trace!(from = ?self.scope, ?to); + self.scope = to; Ok(layer) } - /// Define `self` value. - pub(crate) fn define_self(&mut self) -> Result { - tracing::trace!(?self.scope, "define self"); - - let Some(layer) = self.scopes.get_mut(self.scope.0) else { - return Err(MissingScope(self.scope.0)); - }; - - let variable = self.variables.insert(()); - layer.has_self = Some(variable); - layer.order.push(variable); - Ok(Variable(variable)) - } - /// Define the given variable. - #[tracing::instrument(skip_all)] - pub(crate) fn define(&mut self, name: &'hir str) -> Result { + #[tracing::instrument(skip_all, fields(?self.scope, ?name))] + pub(crate) fn define(&mut self, name: Name<'hir>) -> Result, MissingScope> { tracing::trace!(?self.scope, ?name, "define"); let Some(layer) = self.scopes.get_mut(self.scope.0) else { return Err(MissingScope(self.scope.0)); }; - let variable = self.variables.insert(()); - // Intentionally ignore shadowing variable assignments, since shadowed - // variables aren't dropped until the end of the scope anyways. - layer.variables.insert(name, variable); - layer.order.push(variable); - Ok(Variable(variable)) - } - - /// Try to lookup the self variable. - #[tracing::instrument(skip_all)] - pub(crate) fn get_self(&mut self) -> Option { - tracing::trace!(?self.scope, "get self"); - self.scan(|layer| Some((Variable(layer.has_self?), Name::SelfValue))) + layer.variables.insert(name); + layer.order.push(name); + Ok(name) } /// Try to lookup the given variable. - #[tracing::instrument(skip_all)] - pub(crate) fn get(&mut self, name: &'hir str) -> Option { - tracing::trace!(?self.scope, ?name, "get"); - self.scan(|layer| Some((Variable(*layer.variables.get(name)?), Name::Str(name)))) - } + #[tracing::instrument(skip_all, fields(?self.scope, ?name))] + pub(crate) fn get(&mut self, name: Name<'hir>) -> Option<(Name<'hir>, Scope)> { + tracing::trace!("get"); - fn scan(&mut self, mut f: F) -> Option - where - F: FnMut(&Layer) -> Option<(Variable, Name<'hir>)>, - { let mut blocks = Vec::new(); let mut scope = self.scopes.get(self.scope.0); - let (variable, capture) = 'ok: { - while let Some(s) = scope.take() { - if let Some((variable, capture)) = f(s) { - break 'ok (variable, capture); + let scope = 'ok: { + while let Some(layer) = scope.take() { + if layer.variables.contains(&name) { + break 'ok layer.scope; } - if let LayerKind::Captures { .. } = s.kind { - blocks.push(s.scope); + if let LayerKind::Captures { .. } = layer.kind { + blocks.push(layer.scope); } - tracing::trace!(parent = ?s.parent()); - scope = self.scopes.get(s.parent()?); + tracing::trace!(parent = ?layer.parent()); + scope = self.scopes.get(layer.parent()?); } return None; }; for s in blocks { - let Some(s) = self.scopes.get_mut(s.0) else { + let Some(layer) = self.scopes.get_mut(s.0) else { continue; }; - s.captures.insert((variable, capture)); + layer.captures.insert(name); } - Some(variable) + Some((name, scope)) } } @@ -268,7 +231,6 @@ impl<'hir> Default for Scopes<'hir> { Self { scope: Scopes::ROOT, scopes, - variables: slab::Slab::new(), } } } diff --git a/crates/rune/src/query/query.rs b/crates/rune/src/query/query.rs index 01da3a54f..4e801449c 100644 --- a/crates/rune/src/query/query.rs +++ b/crates/rune/src/query/query.rs @@ -75,7 +75,7 @@ pub(crate) struct QueryInner { /// All available names. names: Names, /// Recorded captures. - captures: HashMap>, + captures: HashMap>, } impl QueryInner { @@ -1665,22 +1665,14 @@ impl<'a> Query<'a> { /// Insert captures. pub(crate) fn insert_captures<'hir, C>(&mut self, hash: Hash, captures: C) where - C: IntoIterator)>, + C: IntoIterator>, { - let captures = captures.into_iter().map(|(v, c)| { - let c = match c { - hir::Name::SelfValue => hir::OwnedCapture::SelfValue, - hir::Name::Str(name) => hir::OwnedCapture::Name(name.to_owned()), - }; - - (v, c) - }); - + let captures = captures.into_iter().map(hir::Name::into_owned); self.inner.captures.insert(hash, captures.collect()); } /// Get captures for the given hash. - pub(crate) fn get_captures(&self, hash: Hash) -> Option<&[(hir::Variable, hir::OwnedCapture)]> { + pub(crate) fn get_captures(&self, hash: Hash) -> Option<&[hir::OwnedName]> { Some(self.inner.captures.get(&hash)?) } }