avoid thunking trivial values
This commit is contained in:
@@ -93,6 +93,9 @@ impl<'a, Ctx: DisassemblerContext> Disassembler<'a, Ctx> {
|
|||||||
self.read_u8();
|
self.read_u8();
|
||||||
self.read_u32();
|
self.read_u32();
|
||||||
}
|
}
|
||||||
|
BuiltinConst => {
|
||||||
|
self.read_u32();
|
||||||
|
}
|
||||||
Builtins => {}
|
Builtins => {}
|
||||||
ReplBinding | ScopedImportBinding | WithLookup => {
|
ReplBinding | ScopedImportBinding | WithLookup => {
|
||||||
self.read_u32();
|
self.read_u32();
|
||||||
|
|||||||
+19
-2
@@ -116,6 +116,7 @@ pub enum OperandType {
|
|||||||
Const,
|
Const,
|
||||||
BigInt,
|
BigInt,
|
||||||
Local,
|
Local,
|
||||||
|
BuiltinConst,
|
||||||
Builtins,
|
Builtins,
|
||||||
ReplBinding,
|
ReplBinding,
|
||||||
ScopedImportBinding,
|
ScopedImportBinding,
|
||||||
@@ -147,6 +148,7 @@ pub enum InlineOperand {
|
|||||||
Const(Const),
|
Const(Const),
|
||||||
BigInt(i64),
|
BigInt(i64),
|
||||||
Local { layer: u8, local: u32 },
|
Local { layer: u8, local: u32 },
|
||||||
|
BuiltinConst(StringId),
|
||||||
Builtins,
|
Builtins,
|
||||||
ReplBinding(StringId),
|
ReplBinding(StringId),
|
||||||
ScopedImportBinding(StringId),
|
ScopedImportBinding(StringId),
|
||||||
@@ -191,8 +193,13 @@ impl<'a, Ctx: BytecodeContext> BytecodeEmitter<'a, Ctx> {
|
|||||||
Arg { layer } => InlineOperand::Local { layer, local: 0 },
|
Arg { layer } => InlineOperand::Local { layer, local: 0 },
|
||||||
Builtin(id) => {
|
Builtin(id) => {
|
||||||
let (_, arity) = BUILTINS[id as usize];
|
let (_, arity) = BUILTINS[id as usize];
|
||||||
InlineOperand::Const(Const::PrimOp { id, arity, dispatch_ip: id.entry_phase().ip() })
|
InlineOperand::Const(Const::PrimOp {
|
||||||
},
|
id,
|
||||||
|
arity,
|
||||||
|
dispatch_ip: id.entry_phase().ip(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
BuiltinConst(id) => InlineOperand::BuiltinConst(id),
|
||||||
Builtins => InlineOperand::Builtins,
|
Builtins => InlineOperand::Builtins,
|
||||||
ReplBinding(id) => InlineOperand::ReplBinding(id),
|
ReplBinding(id) => InlineOperand::ReplBinding(id),
|
||||||
ScopedImportBinding(id) => InlineOperand::ScopedImportBinding(id),
|
ScopedImportBinding(id) => InlineOperand::ScopedImportBinding(id),
|
||||||
@@ -218,6 +225,10 @@ impl<'a, Ctx: BytecodeContext> BytecodeEmitter<'a, Ctx> {
|
|||||||
self.emit_u8(layer);
|
self.emit_u8(layer);
|
||||||
self.emit_u32(local);
|
self.emit_u32(local);
|
||||||
}
|
}
|
||||||
|
BuiltinConst(id) => {
|
||||||
|
self.emit_u8(OperandType::BuiltinConst as u8);
|
||||||
|
self.emit_str_id(id);
|
||||||
|
}
|
||||||
Builtins => {
|
Builtins => {
|
||||||
self.emit_u8(OperandType::Builtins as u8);
|
self.emit_u8(OperandType::Builtins as u8);
|
||||||
}
|
}
|
||||||
@@ -698,6 +709,12 @@ impl<'a, Ctx: BytecodeContext> BytecodeEmitter<'a, Ctx> {
|
|||||||
self.emit_op(Op::LoadBuiltin);
|
self.emit_op(Op::LoadBuiltin);
|
||||||
self.emit_u8(id as u8);
|
self.emit_u8(id as u8);
|
||||||
}
|
}
|
||||||
|
BuiltinConst(id) => self.emit_select(
|
||||||
|
&Ir::Builtins,
|
||||||
|
&[Attr::Str(id, TextRange::default())],
|
||||||
|
None,
|
||||||
|
TextRange::default(),
|
||||||
|
),
|
||||||
Builtins => self.emit_op(Op::LoadBuiltins),
|
Builtins => self.emit_op(Op::LoadBuiltins),
|
||||||
ReplBinding(name) => {
|
ReplBinding(name) => {
|
||||||
self.emit_op(Op::LoadReplBinding);
|
self.emit_op(Op::LoadReplBinding);
|
||||||
|
|||||||
+60
-53
@@ -39,12 +39,12 @@ impl<'id: 'ir, 'ir, Ctx: DowngradeContext<'id, 'ir>, T, E: std::fmt::Display>
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub trait DowngradeContext<'id: 'ir, 'ir> {
|
pub trait DowngradeContext<'id: 'ir, 'ir> {
|
||||||
fn new_expr(&self, expr: Ir<'ir, GhostRef<'id, 'ir>>) -> IrRef<'id, 'ir>;
|
fn new_expr(&self, expr: Ir<'ir, GhostRoRef<'id, 'ir>>) -> GhostRoIrRef<'id, 'ir>;
|
||||||
fn maybe_thunk(&mut self, ir: IrRef<'id, 'ir>) -> GhostMaybeThunkRef<'id, 'ir>;
|
fn maybe_thunk(&mut self, ir: GhostRoIrRef<'id, 'ir>) -> GhostRoMaybeThunkRef<'id, 'ir>;
|
||||||
|
|
||||||
fn intern_string(&mut self, sym: impl AsRef<str>) -> StringId;
|
fn intern_string(&mut self, sym: impl AsRef<str>) -> StringId;
|
||||||
fn resolve_sym(&self, id: StringId) -> Symbol<'_>;
|
fn resolve_sym(&self, id: StringId) -> Symbol<'_>;
|
||||||
fn lookup(&self, sym: StringId, span: TextRange) -> Result<GhostMaybeThunkRef<'id, 'ir>>;
|
fn lookup(&self, sym: StringId, span: TextRange) -> Result<GhostRoMaybeThunkRef<'id, 'ir>>;
|
||||||
|
|
||||||
fn get_current_source(&self) -> Source;
|
fn get_current_source(&self) -> Source;
|
||||||
|
|
||||||
@@ -53,11 +53,11 @@ pub trait DowngradeContext<'id: 'ir, 'ir> {
|
|||||||
F: FnOnce(&mut Self) -> R;
|
F: FnOnce(&mut Self) -> R;
|
||||||
fn with_let_scope<F, R>(&mut self, bindings: &[StringId], f: F) -> Result<R>
|
fn with_let_scope<F, R>(&mut self, bindings: &[StringId], f: F) -> Result<R>
|
||||||
where
|
where
|
||||||
F: FnOnce(&mut Self) -> Result<(Vec<'ir, IrRef<'id, 'ir>>, R)>;
|
F: FnOnce(&mut Self) -> Result<(Vec<'ir, GhostRoMaybeThunkRef<'id, 'ir>>, R)>;
|
||||||
fn with_with_scope<F, R>(&mut self, f: F) -> R
|
fn with_with_scope<F, R>(&mut self, f: F) -> R
|
||||||
where
|
where
|
||||||
F: FnOnce(&mut Self) -> R;
|
F: FnOnce(&mut Self) -> R;
|
||||||
fn with_thunk_scope<F, R>(&mut self, f: F) -> (R, Vec<'ir, (ThunkId, IrRef<'id, 'ir>)>)
|
fn with_thunk_scope<F, R>(&mut self, f: F) -> (R, Vec<'ir, (ThunkId, GhostRoIrRef<'id, 'ir>)>)
|
||||||
where
|
where
|
||||||
F: FnOnce(&mut Self) -> R;
|
F: FnOnce(&mut Self) -> R;
|
||||||
|
|
||||||
@@ -65,11 +65,11 @@ pub trait DowngradeContext<'id: 'ir, 'ir> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub trait Downgrade<'id: 'ir, 'ir, Ctx: DowngradeContext<'id, 'ir>> {
|
pub trait Downgrade<'id: 'ir, 'ir, Ctx: DowngradeContext<'id, 'ir>> {
|
||||||
fn downgrade(self, ctx: &mut Ctx) -> Result<IrRef<'id, 'ir>>;
|
fn downgrade(self, ctx: &mut Ctx) -> Result<GhostRoIrRef<'id, 'ir>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'id: 'ir, 'ir, Ctx: DowngradeContext<'id, 'ir>> Downgrade<'id, 'ir, Ctx> for Expr {
|
impl<'id: 'ir, 'ir, Ctx: DowngradeContext<'id, 'ir>> Downgrade<'id, 'ir, Ctx> for Expr {
|
||||||
fn downgrade(self, ctx: &mut Ctx) -> Result<IrRef<'id, 'ir>> {
|
fn downgrade(self, ctx: &mut Ctx) -> Result<GhostRoIrRef<'id, 'ir>> {
|
||||||
use Expr::*;
|
use Expr::*;
|
||||||
match self {
|
match self {
|
||||||
Apply(apply) => apply.downgrade(ctx),
|
Apply(apply) => apply.downgrade(ctx),
|
||||||
@@ -114,7 +114,7 @@ impl<'id: 'ir, 'ir, Ctx: DowngradeContext<'id, 'ir>> Downgrade<'id, 'ir, Ctx> fo
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'id: 'ir, 'ir, Ctx: DowngradeContext<'id, 'ir>> Downgrade<'id, 'ir, Ctx> for ast::Assert {
|
impl<'id: 'ir, 'ir, Ctx: DowngradeContext<'id, 'ir>> Downgrade<'id, 'ir, Ctx> for ast::Assert {
|
||||||
fn downgrade(self, ctx: &mut Ctx) -> Result<IrRef<'id, 'ir>> {
|
fn downgrade(self, ctx: &mut Ctx) -> Result<GhostRoIrRef<'id, 'ir>> {
|
||||||
let span = self.syntax().text_range();
|
let span = self.syntax().text_range();
|
||||||
let assertion = self.condition().require(ctx, span)?;
|
let assertion = self.condition().require(ctx, span)?;
|
||||||
let assertion_raw = assertion.to_string();
|
let assertion_raw = assertion.to_string();
|
||||||
@@ -130,7 +130,7 @@ impl<'id: 'ir, 'ir, Ctx: DowngradeContext<'id, 'ir>> Downgrade<'id, 'ir, Ctx> fo
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'id: 'ir, 'ir, Ctx: DowngradeContext<'id, 'ir>> Downgrade<'id, 'ir, Ctx> for ast::IfElse {
|
impl<'id: 'ir, 'ir, Ctx: DowngradeContext<'id, 'ir>> Downgrade<'id, 'ir, Ctx> for ast::IfElse {
|
||||||
fn downgrade(self, ctx: &mut Ctx) -> Result<IrRef<'id, 'ir>> {
|
fn downgrade(self, ctx: &mut Ctx) -> Result<GhostRoIrRef<'id, 'ir>> {
|
||||||
let span = self.syntax().text_range();
|
let span = self.syntax().text_range();
|
||||||
let cond = self.condition().require(ctx, span)?.downgrade(ctx)?;
|
let cond = self.condition().require(ctx, span)?.downgrade(ctx)?;
|
||||||
let consq = self.body().require(ctx, span)?.downgrade(ctx)?;
|
let consq = self.body().require(ctx, span)?.downgrade(ctx)?;
|
||||||
@@ -142,7 +142,7 @@ impl<'id: 'ir, 'ir, Ctx: DowngradeContext<'id, 'ir>> Downgrade<'id, 'ir, Ctx> fo
|
|||||||
macro_rules! path {
|
macro_rules! path {
|
||||||
($ty:ident) => {
|
($ty:ident) => {
|
||||||
impl<'id: 'ir, 'ir, Ctx: DowngradeContext<'id, 'ir>> Downgrade<'id, 'ir, Ctx> for ast::$ty {
|
impl<'id: 'ir, 'ir, Ctx: DowngradeContext<'id, 'ir>> Downgrade<'id, 'ir, Ctx> for ast::$ty {
|
||||||
fn downgrade(self, ctx: &mut Ctx) -> Result<IrRef<'id, 'ir>> {
|
fn downgrade(self, ctx: &mut Ctx) -> Result<GhostRoIrRef<'id, 'ir>> {
|
||||||
downgrade_path(self.parts(), ctx)
|
downgrade_path(self.parts(), ctx)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -152,7 +152,7 @@ path!(PathAbs);
|
|||||||
path!(PathRel);
|
path!(PathRel);
|
||||||
path!(PathHome);
|
path!(PathHome);
|
||||||
impl<'id: 'ir, 'ir, Ctx: DowngradeContext<'id, 'ir>> Downgrade<'id, 'ir, Ctx> for ast::PathSearch {
|
impl<'id: 'ir, 'ir, Ctx: DowngradeContext<'id, 'ir>> Downgrade<'id, 'ir, Ctx> for ast::PathSearch {
|
||||||
fn downgrade(self, ctx: &mut Ctx) -> Result<IrRef<'id, 'ir>> {
|
fn downgrade(self, ctx: &mut Ctx) -> Result<GhostRoIrRef<'id, 'ir>> {
|
||||||
let span = self.syntax().text_range();
|
let span = self.syntax().text_range();
|
||||||
let path = {
|
let path = {
|
||||||
let temp = self.content().require(ctx, span)?;
|
let temp = self.content().require(ctx, span)?;
|
||||||
@@ -180,7 +180,7 @@ impl<'id: 'ir, 'ir, Ctx: DowngradeContext<'id, 'ir>> Downgrade<'id, 'ir, Ctx> fo
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'id: 'ir, 'ir, Ctx: DowngradeContext<'id, 'ir>> Downgrade<'id, 'ir, Ctx> for ast::Str {
|
impl<'id: 'ir, 'ir, Ctx: DowngradeContext<'id, 'ir>> Downgrade<'id, 'ir, Ctx> for ast::Str {
|
||||||
fn downgrade(self, ctx: &mut Ctx) -> Result<IrRef<'id, 'ir>> {
|
fn downgrade(self, ctx: &mut Ctx) -> Result<GhostRoIrRef<'id, 'ir>> {
|
||||||
let normalized = self.normalized_parts();
|
let normalized = self.normalized_parts();
|
||||||
let is_single_literal = normalized.len() == 1
|
let is_single_literal = normalized.len() == 1
|
||||||
&& matches!(normalized.first(), Some(ast::InterpolPart::Literal(_)));
|
&& matches!(normalized.first(), Some(ast::InterpolPart::Literal(_)));
|
||||||
@@ -210,7 +210,7 @@ impl<'id: 'ir, 'ir, Ctx: DowngradeContext<'id, 'ir>> Downgrade<'id, 'ir, Ctx> fo
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'id: 'ir, 'ir, Ctx: DowngradeContext<'id, 'ir>> Downgrade<'id, 'ir, Ctx> for ast::Literal {
|
impl<'id: 'ir, 'ir, Ctx: DowngradeContext<'id, 'ir>> Downgrade<'id, 'ir, Ctx> for ast::Literal {
|
||||||
fn downgrade(self, ctx: &mut Ctx) -> Result<IrRef<'id, 'ir>> {
|
fn downgrade(self, ctx: &mut Ctx) -> Result<GhostRoIrRef<'id, 'ir>> {
|
||||||
let span = self.syntax().text_range();
|
let span = self.syntax().text_range();
|
||||||
let expr = match self.kind() {
|
let expr = match self.kind() {
|
||||||
ast::LiteralKind::Integer(int) => Ir::Int(int.value().require(ctx, span)?),
|
ast::LiteralKind::Integer(int) => Ir::Int(int.value().require(ctx, span)?),
|
||||||
@@ -225,7 +225,7 @@ impl<'id: 'ir, 'ir, Ctx: DowngradeContext<'id, 'ir>> Downgrade<'id, 'ir, Ctx> fo
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'id: 'ir, 'ir, Ctx: DowngradeContext<'id, 'ir>> Downgrade<'id, 'ir, Ctx> for ast::Ident {
|
impl<'id: 'ir, 'ir, Ctx: DowngradeContext<'id, 'ir>> Downgrade<'id, 'ir, Ctx> for ast::Ident {
|
||||||
fn downgrade(self, ctx: &mut Ctx) -> Result<IrRef<'id, 'ir>> {
|
fn downgrade(self, ctx: &mut Ctx) -> Result<GhostRoIrRef<'id, 'ir>> {
|
||||||
let span = self.syntax().text_range();
|
let span = self.syntax().text_range();
|
||||||
let text = self.ident_token().require(ctx, span)?.to_string();
|
let text = self.ident_token().require(ctx, span)?.to_string();
|
||||||
let sym = ctx.intern_string(text);
|
let sym = ctx.intern_string(text);
|
||||||
@@ -235,7 +235,7 @@ impl<'id: 'ir, 'ir, Ctx: DowngradeContext<'id, 'ir>> Downgrade<'id, 'ir, Ctx> fo
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'id: 'ir, 'ir, Ctx: DowngradeContext<'id, 'ir>> Downgrade<'id, 'ir, Ctx> for ast::AttrSet {
|
impl<'id: 'ir, 'ir, Ctx: DowngradeContext<'id, 'ir>> Downgrade<'id, 'ir, Ctx> for ast::AttrSet {
|
||||||
fn downgrade(self, ctx: &mut Ctx) -> Result<IrRef<'id, 'ir>> {
|
fn downgrade(self, ctx: &mut Ctx) -> Result<GhostRoIrRef<'id, 'ir>> {
|
||||||
let rec = self.rec_token().is_some();
|
let rec = self.rec_token().is_some();
|
||||||
if !rec {
|
if !rec {
|
||||||
let attrs = downgrade_attrs(self, ctx)?;
|
let attrs = downgrade_attrs(self, ctx)?;
|
||||||
@@ -251,7 +251,7 @@ impl<'id: 'ir, 'ir, Ctx: DowngradeContext<'id, 'ir>> Downgrade<'id, 'ir, Ctx> fo
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'id: 'ir, 'ir, Ctx: DowngradeContext<'id, 'ir>> Downgrade<'id, 'ir, Ctx> for ast::List {
|
impl<'id: 'ir, 'ir, Ctx: DowngradeContext<'id, 'ir>> Downgrade<'id, 'ir, Ctx> for ast::List {
|
||||||
fn downgrade(self, ctx: &mut Ctx) -> Result<IrRef<'id, 'ir>> {
|
fn downgrade(self, ctx: &mut Ctx) -> Result<GhostRoIrRef<'id, 'ir>> {
|
||||||
let bump = ctx.bump();
|
let bump = ctx.bump();
|
||||||
let items = self
|
let items = self
|
||||||
.items()
|
.items()
|
||||||
@@ -265,7 +265,7 @@ impl<'id: 'ir, 'ir, Ctx: DowngradeContext<'id, 'ir>> Downgrade<'id, 'ir, Ctx> fo
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'id: 'ir, 'ir, Ctx: DowngradeContext<'id, 'ir>> Downgrade<'id, 'ir, Ctx> for ast::BinOp {
|
impl<'id: 'ir, 'ir, Ctx: DowngradeContext<'id, 'ir>> Downgrade<'id, 'ir, Ctx> for ast::BinOp {
|
||||||
fn downgrade(self, ctx: &mut Ctx) -> Result<IrRef<'id, 'ir>> {
|
fn downgrade(self, ctx: &mut Ctx) -> Result<GhostRoIrRef<'id, 'ir>> {
|
||||||
let span = self.syntax().text_range();
|
let span = self.syntax().text_range();
|
||||||
let lhs = self.lhs().require(ctx, span)?.downgrade(ctx)?;
|
let lhs = self.lhs().require(ctx, span)?.downgrade(ctx)?;
|
||||||
let rhs = self.rhs().require(ctx, span)?.downgrade(ctx)?;
|
let rhs = self.rhs().require(ctx, span)?.downgrade(ctx)?;
|
||||||
@@ -275,7 +275,7 @@ impl<'id: 'ir, 'ir, Ctx: DowngradeContext<'id, 'ir>> Downgrade<'id, 'ir, Ctx> fo
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'id: 'ir, 'ir, Ctx: DowngradeContext<'id, 'ir>> Downgrade<'id, 'ir, Ctx> for ast::HasAttr {
|
impl<'id: 'ir, 'ir, Ctx: DowngradeContext<'id, 'ir>> Downgrade<'id, 'ir, Ctx> for ast::HasAttr {
|
||||||
fn downgrade(self, ctx: &mut Ctx) -> Result<IrRef<'id, 'ir>> {
|
fn downgrade(self, ctx: &mut Ctx) -> Result<GhostRoIrRef<'id, 'ir>> {
|
||||||
let span = self.syntax().text_range();
|
let span = self.syntax().text_range();
|
||||||
let lhs = self.expr().require(ctx, span)?.downgrade(ctx)?;
|
let lhs = self.expr().require(ctx, span)?.downgrade(ctx)?;
|
||||||
let rhs = downgrade_attrpath(self.attrpath().require(ctx, span)?, ctx)?;
|
let rhs = downgrade_attrpath(self.attrpath().require(ctx, span)?, ctx)?;
|
||||||
@@ -284,7 +284,7 @@ impl<'id: 'ir, 'ir, Ctx: DowngradeContext<'id, 'ir>> Downgrade<'id, 'ir, Ctx> fo
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'id: 'ir, 'ir, Ctx: DowngradeContext<'id, 'ir>> Downgrade<'id, 'ir, Ctx> for ast::UnaryOp {
|
impl<'id: 'ir, 'ir, Ctx: DowngradeContext<'id, 'ir>> Downgrade<'id, 'ir, Ctx> for ast::UnaryOp {
|
||||||
fn downgrade(self, ctx: &mut Ctx) -> Result<IrRef<'id, 'ir>> {
|
fn downgrade(self, ctx: &mut Ctx) -> Result<GhostRoIrRef<'id, 'ir>> {
|
||||||
let span = self.syntax().text_range();
|
let span = self.syntax().text_range();
|
||||||
let rhs = self.expr().require(ctx, span)?.downgrade(ctx)?;
|
let rhs = self.expr().require(ctx, span)?.downgrade(ctx)?;
|
||||||
let kind = self.operator().require(ctx, span)?.into();
|
let kind = self.operator().require(ctx, span)?.into();
|
||||||
@@ -293,7 +293,7 @@ impl<'id: 'ir, 'ir, Ctx: DowngradeContext<'id, 'ir>> Downgrade<'id, 'ir, Ctx> fo
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'id: 'ir, 'ir, Ctx: DowngradeContext<'id, 'ir>> Downgrade<'id, 'ir, Ctx> for ast::Select {
|
impl<'id: 'ir, 'ir, Ctx: DowngradeContext<'id, 'ir>> Downgrade<'id, 'ir, Ctx> for ast::Select {
|
||||||
fn downgrade(self, ctx: &mut Ctx) -> Result<IrRef<'id, 'ir>> {
|
fn downgrade(self, ctx: &mut Ctx) -> Result<GhostRoIrRef<'id, 'ir>> {
|
||||||
let span = self.syntax().text_range();
|
let span = self.syntax().text_range();
|
||||||
let expr = self.expr().require(ctx, span)?.downgrade(ctx)?;
|
let expr = self.expr().require(ctx, span)?.downgrade(ctx)?;
|
||||||
let attrpath = downgrade_attrpath(self.attrpath().require(ctx, span)?, ctx)?;
|
let attrpath = downgrade_attrpath(self.attrpath().require(ctx, span)?, ctx)?;
|
||||||
@@ -312,7 +312,7 @@ impl<'id: 'ir, 'ir, Ctx: DowngradeContext<'id, 'ir>> Downgrade<'id, 'ir, Ctx> fo
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'id: 'ir, 'ir, Ctx: DowngradeContext<'id, 'ir>> Downgrade<'id, 'ir, Ctx> for ast::LegacyLet {
|
impl<'id: 'ir, 'ir, Ctx: DowngradeContext<'id, 'ir>> Downgrade<'id, 'ir, Ctx> for ast::LegacyLet {
|
||||||
fn downgrade(self, ctx: &mut Ctx) -> Result<IrRef<'id, 'ir>> {
|
fn downgrade(self, ctx: &mut Ctx) -> Result<GhostRoIrRef<'id, 'ir>> {
|
||||||
let span = self.syntax().text_range();
|
let span = self.syntax().text_range();
|
||||||
let entries: Vec<'ir, _> = self.entries().collect_in(ctx.bump());
|
let entries: Vec<'ir, _> = self.entries().collect_in(ctx.bump());
|
||||||
let attrset_expr = downgrade_let_bindings(entries, ctx, |ctx, binding_keys| {
|
let attrset_expr = downgrade_let_bindings(entries, ctx, |ctx, binding_keys| {
|
||||||
@@ -341,7 +341,7 @@ impl<'id: 'ir, 'ir, Ctx: DowngradeContext<'id, 'ir>> Downgrade<'id, 'ir, Ctx> fo
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'id: 'ir, 'ir, Ctx: DowngradeContext<'id, 'ir>> Downgrade<'id, 'ir, Ctx> for ast::LetIn {
|
impl<'id: 'ir, 'ir, Ctx: DowngradeContext<'id, 'ir>> Downgrade<'id, 'ir, Ctx> for ast::LetIn {
|
||||||
fn downgrade(self, ctx: &mut Ctx) -> Result<IrRef<'id, 'ir>> {
|
fn downgrade(self, ctx: &mut Ctx) -> Result<GhostRoIrRef<'id, 'ir>> {
|
||||||
let entries: Vec<'ir, _> = self.entries().collect_in(ctx.bump());
|
let entries: Vec<'ir, _> = self.entries().collect_in(ctx.bump());
|
||||||
let span = self.syntax().text_range();
|
let span = self.syntax().text_range();
|
||||||
let body_expr = self.body().require(ctx, span)?;
|
let body_expr = self.body().require(ctx, span)?;
|
||||||
@@ -351,7 +351,7 @@ impl<'id: 'ir, 'ir, Ctx: DowngradeContext<'id, 'ir>> Downgrade<'id, 'ir, Ctx> fo
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'id: 'ir, 'ir, Ctx: DowngradeContext<'id, 'ir>> Downgrade<'id, 'ir, Ctx> for ast::With {
|
impl<'id: 'ir, 'ir, Ctx: DowngradeContext<'id, 'ir>> Downgrade<'id, 'ir, Ctx> for ast::With {
|
||||||
fn downgrade(self, ctx: &mut Ctx) -> Result<IrRef<'id, 'ir>> {
|
fn downgrade(self, ctx: &mut Ctx) -> Result<GhostRoIrRef<'id, 'ir>> {
|
||||||
let span = self.syntax().text_range();
|
let span = self.syntax().text_range();
|
||||||
let namespace = self.namespace().require(ctx, span)?.downgrade(ctx)?;
|
let namespace = self.namespace().require(ctx, span)?.downgrade(ctx)?;
|
||||||
let namespace = ctx.maybe_thunk(namespace);
|
let namespace = ctx.maybe_thunk(namespace);
|
||||||
@@ -370,14 +370,14 @@ impl<'id: 'ir, 'ir, Ctx: DowngradeContext<'id, 'ir>> Downgrade<'id, 'ir, Ctx> fo
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'id: 'ir, 'ir, Ctx: DowngradeContext<'id, 'ir>> Downgrade<'id, 'ir, Ctx> for ast::Lambda {
|
impl<'id: 'ir, 'ir, Ctx: DowngradeContext<'id, 'ir>> Downgrade<'id, 'ir, Ctx> for ast::Lambda {
|
||||||
fn downgrade(self, ctx: &mut Ctx) -> Result<IrRef<'id, 'ir>> {
|
fn downgrade(self, ctx: &mut Ctx) -> Result<GhostRoIrRef<'id, 'ir>> {
|
||||||
let span = self.syntax().text_range();
|
let span = self.syntax().text_range();
|
||||||
let raw_param = self.param().require(ctx, span)?;
|
let raw_param = self.param().require(ctx, span)?;
|
||||||
let body_ast = self.body().require(ctx, span)?;
|
let body_ast = self.body().require(ctx, span)?;
|
||||||
|
|
||||||
struct Ret<'id, 'ir> {
|
struct Ret<'id, 'ir> {
|
||||||
param: Option<Param<'ir>>,
|
param: Option<Param<'ir>>,
|
||||||
body: IrRef<'id, 'ir>,
|
body: GhostRoIrRef<'id, 'ir>,
|
||||||
}
|
}
|
||||||
|
|
||||||
let (ret, thunks) = ctx.with_thunk_scope(|ctx| {
|
let (ret, thunks) = ctx.with_thunk_scope(|ctx| {
|
||||||
@@ -434,7 +434,7 @@ impl<'id: 'ir, 'ir, Ctx: DowngradeContext<'id, 'ir>> Downgrade<'id, 'ir, Ctx> fo
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'id: 'ir, 'ir, Ctx: DowngradeContext<'id, 'ir>> Downgrade<'id, 'ir, Ctx> for ast::Apply {
|
impl<'id: 'ir, 'ir, Ctx: DowngradeContext<'id, 'ir>> Downgrade<'id, 'ir, Ctx> for ast::Apply {
|
||||||
fn downgrade(self, ctx: &mut Ctx) -> Result<IrRef<'id, 'ir>> {
|
fn downgrade(self, ctx: &mut Ctx) -> Result<GhostRoIrRef<'id, 'ir>> {
|
||||||
let span = self.syntax().text_range();
|
let span = self.syntax().text_range();
|
||||||
let func = self.lambda().require(ctx, span)?.downgrade(ctx)?;
|
let func = self.lambda().require(ctx, span)?.downgrade(ctx)?;
|
||||||
let arg = self.argument().require(ctx, span)?.downgrade(ctx)?;
|
let arg = self.argument().require(ctx, span)?.downgrade(ctx)?;
|
||||||
@@ -836,8 +836,15 @@ fn make_attrpath_value_entry<'ir>(path: Vec<'ir, ast::Attr>, value: ast::Expr) -
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct FinalizedAttrSet<'id, 'ir> {
|
struct FinalizedAttrSet<'id, 'ir> {
|
||||||
stcs: HashMap<'ir, StringId, (GhostMaybeThunkRef<'id, 'ir>, TextRange)>,
|
stcs: HashMap<'ir, StringId, (GhostRoMaybeThunkRef<'id, 'ir>, TextRange)>,
|
||||||
dyns: Vec<'ir, (IrRef<'id, 'ir>, GhostMaybeThunkRef<'id, 'ir>, TextRange)>,
|
dyns: Vec<
|
||||||
|
'ir,
|
||||||
|
(
|
||||||
|
GhostRoIrRef<'id, 'ir>,
|
||||||
|
GhostRoMaybeThunkRef<'id, 'ir>,
|
||||||
|
TextRange,
|
||||||
|
),
|
||||||
|
>,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn downgrade_attrs<'id, 'ir>(
|
fn downgrade_attrs<'id, 'ir>(
|
||||||
@@ -852,7 +859,7 @@ fn downgrade_attrs<'id, 'ir>(
|
|||||||
fn downgrade_attr<'id, 'ir>(
|
fn downgrade_attr<'id, 'ir>(
|
||||||
attr: ast::Attr,
|
attr: ast::Attr,
|
||||||
ctx: &mut impl DowngradeContext<'id, 'ir>,
|
ctx: &mut impl DowngradeContext<'id, 'ir>,
|
||||||
) -> Result<Attr<IrRef<'id, 'ir>>> {
|
) -> Result<Attr<GhostRoIrRef<'id, 'ir>>> {
|
||||||
use ast::Attr::*;
|
use ast::Attr::*;
|
||||||
use ast::InterpolPart::*;
|
use ast::InterpolPart::*;
|
||||||
match attr {
|
match attr {
|
||||||
@@ -913,7 +920,7 @@ fn downgrade_attr<'id, 'ir>(
|
|||||||
fn downgrade_attrpath<'id, 'ir>(
|
fn downgrade_attrpath<'id, 'ir>(
|
||||||
attrpath: ast::Attrpath,
|
attrpath: ast::Attrpath,
|
||||||
ctx: &mut impl DowngradeContext<'id, 'ir>,
|
ctx: &mut impl DowngradeContext<'id, 'ir>,
|
||||||
) -> Result<Vec<'ir, Attr<IrRef<'id, 'ir>>>> {
|
) -> Result<Vec<'ir, Attr<GhostRoIrRef<'id, 'ir>>>> {
|
||||||
let bump = ctx.bump();
|
let bump = ctx.bump();
|
||||||
attrpath
|
attrpath
|
||||||
.attrs()
|
.attrs()
|
||||||
@@ -922,7 +929,7 @@ fn downgrade_attrpath<'id, 'ir>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct PatternBindings<'id, 'ir> {
|
struct PatternBindings<'id, 'ir> {
|
||||||
body: IrRef<'id, 'ir>,
|
body: GhostRoIrRef<'id, 'ir>,
|
||||||
required: Vec<'ir, (StringId, TextRange)>,
|
required: Vec<'ir, (StringId, TextRange)>,
|
||||||
optional: Vec<'ir, (StringId, TextRange)>,
|
optional: Vec<'ir, (StringId, TextRange)>,
|
||||||
}
|
}
|
||||||
@@ -931,7 +938,7 @@ fn downgrade_pattern_bindings<'id, 'ir, Ctx>(
|
|||||||
pat_entries: impl Iterator<Item = ast::PatEntry>,
|
pat_entries: impl Iterator<Item = ast::PatEntry>,
|
||||||
alias: Option<StringId>,
|
alias: Option<StringId>,
|
||||||
ctx: &mut Ctx,
|
ctx: &mut Ctx,
|
||||||
body_fn: impl FnOnce(&mut Ctx, &[StringId]) -> Result<IrRef<'id, 'ir>>,
|
body_fn: impl FnOnce(&mut Ctx, &[StringId]) -> Result<GhostRoIrRef<'id, 'ir>>,
|
||||||
) -> Result<PatternBindings<'id, 'ir>>
|
) -> Result<PatternBindings<'id, 'ir>>
|
||||||
where
|
where
|
||||||
Ctx: DowngradeContext<'id, 'ir>,
|
Ctx: DowngradeContext<'id, 'ir>,
|
||||||
@@ -990,6 +997,7 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
let arg = ctx.new_expr(Ir::Arg { layer: 0 });
|
let arg = ctx.new_expr(Ir::Arg { layer: 0 });
|
||||||
|
let arg_thunk = ctx.maybe_thunk(arg);
|
||||||
ctx.with_let_scope(&keys, |ctx| {
|
ctx.with_let_scope(&keys, |ctx| {
|
||||||
let vals = params
|
let vals = params
|
||||||
.into_iter()
|
.into_iter()
|
||||||
@@ -1001,21 +1009,16 @@ where
|
|||||||
span,
|
span,
|
||||||
} = param;
|
} = param;
|
||||||
let default = default.map(|default| default.downgrade(ctx)).transpose()?;
|
let default = default.map(|default| default.downgrade(ctx)).transpose()?;
|
||||||
// let default = if let Some(default) = default {
|
|
||||||
// let default = default.clone().downgrade(ctx)?;
|
|
||||||
// Some(ctx.maybe_thunk(default))
|
|
||||||
// } else {
|
|
||||||
// None
|
|
||||||
// };
|
|
||||||
|
|
||||||
Ok(ctx.new_expr(Ir::Select {
|
let expr = ctx.new_expr(Ir::Select {
|
||||||
expr: arg,
|
expr: arg,
|
||||||
attrpath: Vec::from_iter_in([Attr::Str(sym, sym_span)], bump),
|
attrpath: Vec::from_iter_in([Attr::Str(sym, sym_span)], bump),
|
||||||
default,
|
default,
|
||||||
span,
|
span,
|
||||||
}))
|
});
|
||||||
|
Ok(ctx.maybe_thunk(expr))
|
||||||
})
|
})
|
||||||
.chain(alias.into_iter().map(|_| Ok(arg)))
|
.chain(alias.into_iter().map(|_| Ok(arg_thunk)))
|
||||||
.collect_in::<Result<_>>(bump)?;
|
.collect_in::<Result<_>>(bump)?;
|
||||||
|
|
||||||
let body = body_fn(ctx, &keys)?;
|
let body = body_fn(ctx, &keys)?;
|
||||||
@@ -1035,10 +1038,10 @@ fn downgrade_let_bindings<'id, 'ir, Ctx, F>(
|
|||||||
entries: Vec<'ir, ast::Entry>,
|
entries: Vec<'ir, ast::Entry>,
|
||||||
ctx: &mut Ctx,
|
ctx: &mut Ctx,
|
||||||
body_fn: F,
|
body_fn: F,
|
||||||
) -> Result<IrRef<'id, 'ir>>
|
) -> Result<GhostRoIrRef<'id, 'ir>>
|
||||||
where
|
where
|
||||||
Ctx: DowngradeContext<'id, 'ir>,
|
Ctx: DowngradeContext<'id, 'ir>,
|
||||||
F: FnOnce(&mut Ctx, &[StringId]) -> Result<IrRef<'id, 'ir>>,
|
F: FnOnce(&mut Ctx, &[StringId]) -> Result<GhostRoIrRef<'id, 'ir>>,
|
||||||
{
|
{
|
||||||
downgrade_rec_attrs_impl::<_, _, false>(entries, ctx, |ctx, binding_keys, _dyns| {
|
downgrade_rec_attrs_impl::<_, _, false>(entries, ctx, |ctx, binding_keys, _dyns| {
|
||||||
body_fn(ctx, binding_keys)
|
body_fn(ctx, binding_keys)
|
||||||
@@ -1048,7 +1051,7 @@ where
|
|||||||
fn downgrade_rec_bindings<'id, 'ir, Ctx>(
|
fn downgrade_rec_bindings<'id, 'ir, Ctx>(
|
||||||
entries: Vec<'ir, ast::Entry>,
|
entries: Vec<'ir, ast::Entry>,
|
||||||
ctx: &mut Ctx,
|
ctx: &mut Ctx,
|
||||||
) -> Result<IrRef<'id, 'ir>>
|
) -> Result<GhostRoIrRef<'id, 'ir>>
|
||||||
where
|
where
|
||||||
Ctx: DowngradeContext<'id, 'ir>,
|
Ctx: DowngradeContext<'id, 'ir>,
|
||||||
{
|
{
|
||||||
@@ -1069,14 +1072,18 @@ fn downgrade_rec_attrs_impl<'id, 'ir, Ctx, F, const ALLOW_DYN: bool>(
|
|||||||
entries: Vec<'ir, ast::Entry>,
|
entries: Vec<'ir, ast::Entry>,
|
||||||
ctx: &mut Ctx,
|
ctx: &mut Ctx,
|
||||||
body_fn: F,
|
body_fn: F,
|
||||||
) -> Result<IrRef<'id, 'ir>>
|
) -> Result<GhostRoIrRef<'id, 'ir>>
|
||||||
where
|
where
|
||||||
Ctx: DowngradeContext<'id, 'ir>,
|
Ctx: DowngradeContext<'id, 'ir>,
|
||||||
F: FnOnce(
|
F: FnOnce(
|
||||||
&mut Ctx,
|
&mut Ctx,
|
||||||
&[StringId],
|
&[StringId],
|
||||||
&[(IrRef<'id, 'ir>, GhostMaybeThunkRef<'id, 'ir>, TextRange)],
|
&[(
|
||||||
) -> Result<IrRef<'id, 'ir>>,
|
GhostRoIrRef<'id, 'ir>,
|
||||||
|
GhostRoMaybeThunkRef<'id, 'ir>,
|
||||||
|
TextRange,
|
||||||
|
)],
|
||||||
|
) -> Result<GhostRoIrRef<'id, 'ir>>,
|
||||||
{
|
{
|
||||||
let mut pending = PendingAttrSet::new_in(ctx.bump());
|
let mut pending = PendingAttrSet::new_in(ctx.bump());
|
||||||
pending.collect_entries(entries.iter().cloned(), ctx)?;
|
pending.collect_entries(entries.iter().cloned(), ctx)?;
|
||||||
@@ -1091,7 +1098,7 @@ where
|
|||||||
let vals = {
|
let vals = {
|
||||||
let mut temp = Vec::with_capacity_in(keys.len(), ctx.bump());
|
let mut temp = Vec::with_capacity_in(keys.len(), ctx.bump());
|
||||||
for sym in &keys {
|
for sym in &keys {
|
||||||
temp.push(ctx.new_expr(Ir::MaybeThunk(finalized.stcs.get(sym).expect("WTF").0)));
|
temp.push(finalized.stcs.get(sym).expect("WTF").0);
|
||||||
}
|
}
|
||||||
temp
|
temp
|
||||||
};
|
};
|
||||||
@@ -1102,7 +1109,7 @@ where
|
|||||||
fn collect_inherit_lookups<'id: 'ir, 'ir, Ctx: DowngradeContext<'id, 'ir>>(
|
fn collect_inherit_lookups<'id: 'ir, 'ir, Ctx: DowngradeContext<'id, 'ir>>(
|
||||||
entries: &[ast::Entry],
|
entries: &[ast::Entry],
|
||||||
ctx: &mut Ctx,
|
ctx: &mut Ctx,
|
||||||
) -> Result<HashMap<'ir, StringId, (GhostMaybeThunkRef<'id, 'ir>, TextRange)>> {
|
) -> Result<HashMap<'ir, StringId, (GhostRoMaybeThunkRef<'id, 'ir>, TextRange)>> {
|
||||||
let mut inherit_lookups = HashMap::new_in(ctx.bump());
|
let mut inherit_lookups = HashMap::new_in(ctx.bump());
|
||||||
for entry in entries {
|
for entry in entries {
|
||||||
if let ast::Entry::Inherit(inherit) = entry
|
if let ast::Entry::Inherit(inherit) = entry
|
||||||
@@ -1142,7 +1149,7 @@ fn collect_binding_syms<'id: 'ir, 'ir, Ctx: DowngradeContext<'id, 'ir>, const AL
|
|||||||
|
|
||||||
fn finalize_pending_set<'id, 'ir, Ctx: DowngradeContext<'id, 'ir>, const ALLOW_DYN: bool>(
|
fn finalize_pending_set<'id, 'ir, Ctx: DowngradeContext<'id, 'ir>, const ALLOW_DYN: bool>(
|
||||||
pending: PendingAttrSet,
|
pending: PendingAttrSet,
|
||||||
inherit_lookups: &HashMap<StringId, (GhostMaybeThunkRef<'id, 'ir>, TextRange)>,
|
inherit_lookups: &HashMap<StringId, (GhostRoMaybeThunkRef<'id, 'ir>, TextRange)>,
|
||||||
ctx: &mut Ctx,
|
ctx: &mut Ctx,
|
||||||
) -> Result<FinalizedAttrSet<'id, 'ir>> {
|
) -> Result<FinalizedAttrSet<'id, 'ir>> {
|
||||||
let mut stcs = HashMap::new_in(ctx.bump());
|
let mut stcs = HashMap::new_in(ctx.bump());
|
||||||
@@ -1170,9 +1177,9 @@ fn finalize_pending_set<'id, 'ir, Ctx: DowngradeContext<'id, 'ir>, const ALLOW_D
|
|||||||
|
|
||||||
fn finalize_pending_value<'id, 'ir, Ctx: DowngradeContext<'id, 'ir>, const ALLOW_DYN: bool>(
|
fn finalize_pending_value<'id, 'ir, Ctx: DowngradeContext<'id, 'ir>, const ALLOW_DYN: bool>(
|
||||||
value: PendingValue,
|
value: PendingValue,
|
||||||
inherit_lookups: &HashMap<StringId, (GhostMaybeThunkRef<'id, 'ir>, TextRange)>,
|
inherit_lookups: &HashMap<StringId, (GhostRoMaybeThunkRef<'id, 'ir>, TextRange)>,
|
||||||
ctx: &mut Ctx,
|
ctx: &mut Ctx,
|
||||||
) -> Result<IrRef<'id, 'ir>> {
|
) -> Result<GhostRoIrRef<'id, 'ir>> {
|
||||||
match value {
|
match value {
|
||||||
PendingValue::Expr(expr) => expr.downgrade(ctx),
|
PendingValue::Expr(expr) => expr.downgrade(ctx),
|
||||||
PendingValue::InheritFrom(from_expr, sym, span) => {
|
PendingValue::InheritFrom(from_expr, sym, span) => {
|
||||||
@@ -1212,7 +1219,7 @@ fn finalize_pending_value<'id, 'ir, Ctx: DowngradeContext<'id, 'ir>, const ALLOW
|
|||||||
fn downgrade_path<'id, 'ir>(
|
fn downgrade_path<'id, 'ir>(
|
||||||
parts: impl IntoIterator<Item = ast::InterpolPart<ast::PathContent>>,
|
parts: impl IntoIterator<Item = ast::InterpolPart<ast::PathContent>>,
|
||||||
ctx: &mut impl DowngradeContext<'id, 'ir>,
|
ctx: &mut impl DowngradeContext<'id, 'ir>,
|
||||||
) -> Result<IrRef<'id, 'ir>> {
|
) -> Result<GhostRoIrRef<'id, 'ir>> {
|
||||||
let bump = ctx.bump();
|
let bump = ctx.bump();
|
||||||
let parts = parts
|
let parts = parts
|
||||||
.into_iter()
|
.into_iter()
|
||||||
|
|||||||
+54
-16
@@ -14,14 +14,16 @@ pub mod downgrade;
|
|||||||
|
|
||||||
pub type HashMap<'ir, K, V> = hashbrown::HashMap<K, V, hashbrown::DefaultHashBuilder, &'ir Bump>;
|
pub type HashMap<'ir, K, V> = hashbrown::HashMap<K, V, hashbrown::DefaultHashBuilder, &'ir Bump>;
|
||||||
|
|
||||||
pub type IrRef<'id, 'ir> = <GhostRef<'id, 'ir> as RefExt<'ir>>::IrRef;
|
pub type GhostIrRef<'id, 'ir> = <GhostRef<'id, 'ir> as RefExt<'ir>>::IrRef;
|
||||||
|
pub type GhostRoIrRef<'id, 'ir> = <GhostRoRef<'id, 'ir> as RefExt<'ir>>::IrRef;
|
||||||
pub type RawIrRef<'ir> = <RawRef<'ir> as RefExt<'ir>>::IrRef;
|
pub type RawIrRef<'ir> = <RawRef<'ir> as RefExt<'ir>>::IrRef;
|
||||||
pub type GhostMaybeThunkRef<'id, 'ir> = <GhostRef<'id, 'ir> as RefExt<'ir>>::MaybeThunkRef;
|
pub type GhostMaybeThunkRef<'id, 'ir> = <GhostRef<'id, 'ir> as RefExt<'ir>>::MaybeThunkRef;
|
||||||
|
pub type GhostRoMaybeThunkRef<'id, 'ir> = <GhostRoRef<'id, 'ir> as RefExt<'ir>>::MaybeThunkRef;
|
||||||
|
|
||||||
impl<'id, 'ir> Ir<'ir, GhostRef<'id, 'ir>> {
|
impl<'id, 'ir> Ir<'ir, GhostRoRef<'id, 'ir>> {
|
||||||
/// Freeze a mutable IR reference into a read-only one, consuming the
|
/// Freeze a mutable IR reference into a read-only one, consuming the
|
||||||
/// `GhostToken` to prevent any further mutation.
|
/// `GhostToken` to prevent any further mutation.
|
||||||
pub fn freeze(this: IrRef<'id, 'ir>, _: GhostToken<'id>) -> RawIrRef<'ir> {
|
pub fn freeze(this: GhostRoIrRef<'id, 'ir>, _: GhostToken<'id>) -> RawIrRef<'ir> {
|
||||||
// SAFETY: The transmute is sound because:
|
// SAFETY: The transmute is sound because:
|
||||||
// - `GhostCell<'id, T>` is `#[repr(transparent)]` over `T`, so
|
// - `GhostCell<'id, T>` is `#[repr(transparent)]` over `T`, so
|
||||||
// `&'ir GhostCell<'id, T>` and `&'ir T` have identical layout.
|
// `&'ir GhostCell<'id, T>` and `&'ir T` have identical layout.
|
||||||
@@ -39,7 +41,39 @@ impl<'id, 'ir> Ir<'ir, GhostRef<'id, 'ir>> {
|
|||||||
// Consuming the `GhostToken` guarantees no `borrow_mut` calls can
|
// Consuming the `GhostToken` guarantees no `borrow_mut` calls can
|
||||||
// occur afterwards, so the shared `&Ir` references reachable from a
|
// occur afterwards, so the shared `&Ir` references reachable from a
|
||||||
// `RawIrRef<'ir>` can never alias with mutable references.
|
// `RawIrRef<'ir>` can never alias with mutable references.
|
||||||
unsafe { std::mem::transmute::<IrRef<'id, 'ir>, RawIrRef<'ir>>(this) }
|
unsafe { std::mem::transmute::<GhostRoIrRef<'id, 'ir>, RawIrRef<'ir>>(this) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[repr(transparent)]
|
||||||
|
pub struct GhostRoCell<'id, T: ?Sized>(GhostCell<'id, T>);
|
||||||
|
|
||||||
|
impl<'id, T> From<GhostCell<'id, T>> for GhostRoCell<'id, T> {
|
||||||
|
fn from(value: GhostCell<'id, T>) -> Self {
|
||||||
|
Self(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'id, T: ?Sized> From<&GhostCell<'id, T>> for &GhostRoCell<'id, T> {
|
||||||
|
fn from(value: &GhostCell<'id, T>) -> Self {
|
||||||
|
// SAFETY: `GhostRoCell` is `#[repr(transparent)]` over `GhostCell`
|
||||||
|
// TODO: document mutability
|
||||||
|
unsafe { std::mem::transmute(value) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'id, T: ?Sized> From<&T> for &GhostRoCell<'id, T> {
|
||||||
|
fn from(value: &T) -> Self {
|
||||||
|
// SAFETY: `GhostRoCell` is `#[repr(transparent)]` over `GhostCell`,
|
||||||
|
// which is `#[repr(transparent)]` over `T`
|
||||||
|
// TODO: document mutability
|
||||||
|
unsafe { std::mem::transmute(value) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'id, T: ?Sized> GhostRoCell<'id, T> {
|
||||||
|
pub fn borrow<'a>(&'a self, token: &'a GhostToken<'id>) -> &'a T {
|
||||||
|
self.0.borrow(token)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -55,13 +89,13 @@ pub enum MaybeThunk {
|
|||||||
Thunk(ThunkId),
|
Thunk(ThunkId),
|
||||||
Arg { layer: u8 },
|
Arg { layer: u8 },
|
||||||
Builtin(BuiltinId),
|
Builtin(BuiltinId),
|
||||||
|
BuiltinConst(StringId),
|
||||||
Builtins,
|
Builtins,
|
||||||
ReplBinding(StringId),
|
ReplBinding(StringId),
|
||||||
ScopedImportBinding(StringId),
|
ScopedImportBinding(StringId),
|
||||||
WithLookup(StringId),
|
WithLookup(StringId),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pub trait Ref<'ir> {
|
pub trait Ref<'ir> {
|
||||||
type Ref<T>
|
type Ref<T>
|
||||||
where
|
where
|
||||||
@@ -80,11 +114,15 @@ impl<'ir, T: Ref<'ir> + 'ir> RefExt<'ir> for T {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub struct GhostRef<'id, 'ir>(PhantomData<&'ir GhostCell<'id, ()>>);
|
pub struct GhostRef<'id, 'ir>(PhantomData<&'ir GhostCell<'id, ()>>);
|
||||||
|
pub struct GhostRoRef<'id, 'ir>(PhantomData<&'ir GhostRoCell<'id, ()>>);
|
||||||
pub struct RawRef<'ir>(PhantomData<&'ir ()>);
|
pub struct RawRef<'ir>(PhantomData<&'ir ()>);
|
||||||
|
|
||||||
impl<'id, 'ir> Ref<'ir> for GhostRef<'id, 'ir> {
|
impl<'id, 'ir> Ref<'ir> for GhostRef<'id, 'ir> {
|
||||||
type Ref<T: 'ir> = &'ir GhostCell<'id, T>;
|
type Ref<T: 'ir> = &'ir GhostCell<'id, T>;
|
||||||
}
|
}
|
||||||
|
impl<'id, 'ir> Ref<'ir> for GhostRoRef<'id, 'ir> {
|
||||||
|
type Ref<T: 'ir> = &'ir GhostRoCell<'id, T>;
|
||||||
|
}
|
||||||
impl<'ir> Ref<'ir> for RawRef<'ir> {
|
impl<'ir> Ref<'ir> for RawRef<'ir> {
|
||||||
type Ref<T: 'ir> = &'ir T;
|
type Ref<T: 'ir> = &'ir T;
|
||||||
}
|
}
|
||||||
@@ -285,38 +323,38 @@ pub struct Param<'ir> {
|
|||||||
|
|
||||||
pub fn new_global_env(
|
pub fn new_global_env(
|
||||||
strings: &mut DefaultStringInterner,
|
strings: &mut DefaultStringInterner,
|
||||||
) -> hashbrown::HashMap<StringId, Ir<'static, RawRef<'static>>> {
|
) -> hashbrown::HashMap<StringId, MaybeThunk> {
|
||||||
let mut global_env = hashbrown::HashMap::new();
|
let mut global_env = hashbrown::HashMap::new();
|
||||||
let builtins_sym = StringId(strings.get_or_intern("builtins"));
|
let builtins_sym = StringId(strings.get_or_intern("builtins"));
|
||||||
global_env.insert(builtins_sym, Ir::Builtins);
|
global_env.insert(builtins_sym, MaybeThunk::Builtins);
|
||||||
|
|
||||||
for (idx, &(name, _)) in BUILTINS.iter().enumerate() {
|
for (idx, &(name, _)) in BUILTINS.iter().enumerate() {
|
||||||
let id = BuiltinId::try_from_primitive(idx as u8).expect("infallible");
|
let id = BuiltinId::try_from_primitive(idx as u8).expect("infallible");
|
||||||
let name = StringId(strings.get_or_intern(name));
|
let name = StringId(strings.get_or_intern(name));
|
||||||
global_env.insert(name, Ir::Builtin(id));
|
global_env.insert(name, MaybeThunk::Builtin(id));
|
||||||
}
|
}
|
||||||
|
|
||||||
let consts = [
|
let consts = [
|
||||||
(
|
(
|
||||||
"__currentSystem",
|
"__currentSystem",
|
||||||
Ir::BuiltinConst(StringId(strings.get_or_intern("currentSystem"))),
|
MaybeThunk::BuiltinConst(StringId(strings.get_or_intern("currentSystem"))),
|
||||||
),
|
),
|
||||||
("__langVersion", Ir::Int(6)),
|
("__langVersion", MaybeThunk::Int(6)),
|
||||||
(
|
(
|
||||||
"__nixVersion",
|
"__nixVersion",
|
||||||
Ir::BuiltinConst(StringId(strings.get_or_intern("nixVersion"))),
|
MaybeThunk::BuiltinConst(StringId(strings.get_or_intern("nixVersion"))),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
"__storeDir",
|
"__storeDir",
|
||||||
Ir::BuiltinConst(StringId(strings.get_or_intern("storeDir"))),
|
MaybeThunk::BuiltinConst(StringId(strings.get_or_intern("storeDir"))),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
"__nixPath",
|
"__nixPath",
|
||||||
Ir::BuiltinConst(StringId(strings.get_or_intern("nixPath"))),
|
MaybeThunk::BuiltinConst(StringId(strings.get_or_intern("nixPath"))),
|
||||||
),
|
),
|
||||||
("null", Ir::Null),
|
("null", MaybeThunk::Null),
|
||||||
("true", Ir::Bool(true)),
|
("true", MaybeThunk::Bool(true)),
|
||||||
("false", Ir::Bool(false)),
|
("false", MaybeThunk::Bool(false)),
|
||||||
];
|
];
|
||||||
|
|
||||||
for (name, ir) in consts {
|
for (name, ir) in consts {
|
||||||
|
|||||||
@@ -112,6 +112,10 @@ impl<'a> BytecodeReader<'a> {
|
|||||||
let idx = self.read_u32();
|
let idx = self.read_u32();
|
||||||
OperandData::Local { layer, idx }
|
OperandData::Local { layer, idx }
|
||||||
}
|
}
|
||||||
|
OperandType::BuiltinConst => {
|
||||||
|
let id = self.read_string_id();
|
||||||
|
OperandData::BuiltinConst(id)
|
||||||
|
}
|
||||||
OperandType::Builtins => OperandData::Builtins,
|
OperandType::Builtins => OperandData::Builtins,
|
||||||
OperandType::ReplBinding => {
|
OperandType::ReplBinding => {
|
||||||
let id = self.read_string_id();
|
let id = self.read_string_id();
|
||||||
|
|||||||
@@ -229,6 +229,7 @@ pub(crate) enum OperandData {
|
|||||||
Const(StaticValue),
|
Const(StaticValue),
|
||||||
BigInt(i64),
|
BigInt(i64),
|
||||||
Local { layer: u8, idx: u32 },
|
Local { layer: u8, idx: u32 },
|
||||||
|
BuiltinConst(StringId),
|
||||||
Builtins,
|
Builtins,
|
||||||
ReplBinding(StringId),
|
ReplBinding(StringId),
|
||||||
ScopedImportBinding(StringId),
|
ScopedImportBinding(StringId),
|
||||||
@@ -249,6 +250,13 @@ impl OperandData {
|
|||||||
}
|
}
|
||||||
cur.borrow().locals[idx as usize]
|
cur.borrow().locals[idx as usize]
|
||||||
}
|
}
|
||||||
|
#[allow(clippy::unwrap_used)]
|
||||||
|
BuiltinConst(id) => root
|
||||||
|
.builtins
|
||||||
|
.as_gc::<AttrSet>()
|
||||||
|
.unwrap()
|
||||||
|
.lookup(id)
|
||||||
|
.unwrap(),
|
||||||
Builtins => root.builtins,
|
Builtins => root.builtins,
|
||||||
ReplBinding(_id) => todo!(),
|
ReplBinding(_id) => todo!(),
|
||||||
ScopedImportBinding(_id) => todo!(),
|
ScopedImportBinding(_id) => todo!(),
|
||||||
|
|||||||
+60
-42
@@ -8,7 +8,10 @@ use fix_codegen::{BytecodeContext, InstructionPtr, Op};
|
|||||||
use fix_common::{StringId, Symbol};
|
use fix_common::{StringId, Symbol};
|
||||||
use fix_error::{Error, Result, Source};
|
use fix_error::{Error, Result, Source};
|
||||||
use fix_ir::downgrade::{Downgrade as _, DowngradeContext};
|
use fix_ir::downgrade::{Downgrade as _, DowngradeContext};
|
||||||
use fix_ir::{GhostMaybeThunkRef, GhostRef, Ir, IrRef, MaybeThunk, RawIrRef, RawRef, ThunkId};
|
use fix_ir::{
|
||||||
|
GhostMaybeThunkRef, GhostRoIrRef, GhostRoMaybeThunkRef, GhostRoRef, Ir, MaybeThunk, RawIrRef,
|
||||||
|
ThunkId,
|
||||||
|
};
|
||||||
use fix_vm::{ForceMode, StaticValue, Vm, VmCode, VmContext, VmRuntimeCtx};
|
use fix_vm::{ForceMode, StaticValue, Vm, VmCode, VmContext, VmRuntimeCtx};
|
||||||
use ghost_cell::{GhostCell, GhostToken};
|
use ghost_cell::{GhostCell, GhostToken};
|
||||||
use hashbrown::{HashMap, HashSet};
|
use hashbrown::{HashMap, HashSet};
|
||||||
@@ -30,7 +33,7 @@ pub struct CodeState {
|
|||||||
pub sources: Vec<Source>,
|
pub sources: Vec<Source>,
|
||||||
pub spans: Vec<(usize, rnix::TextRange)>,
|
pub spans: Vec<(usize, rnix::TextRange)>,
|
||||||
pub thunk_count: usize,
|
pub thunk_count: usize,
|
||||||
pub global_env: HashMap<StringId, Ir<'static, RawRef<'static>>>,
|
pub global_env: HashMap<StringId, MaybeThunk>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Evaluator {
|
pub struct Evaluator {
|
||||||
@@ -323,7 +326,7 @@ impl<'ctx, 'id, 'ir, R: VmRuntimeCtx> DowngradeCtx<'ctx, 'id, 'ir, R> {
|
|||||||
bump: &'ir Bump,
|
bump: &'ir Bump,
|
||||||
token: GhostToken<'id>,
|
token: GhostToken<'id>,
|
||||||
runtime: &'ctx mut R,
|
runtime: &'ctx mut R,
|
||||||
global: &'ctx HashMap<StringId, Ir<'static, RawRef<'static>>>,
|
global: &'ctx HashMap<StringId, MaybeThunk>,
|
||||||
extra_scope: Option<Scope<'ctx, 'id, 'ir>>,
|
extra_scope: Option<Scope<'ctx, 'id, 'ir>>,
|
||||||
thunk_count: &'ctx mut usize,
|
thunk_count: &'ctx mut usize,
|
||||||
source: Source,
|
source: Source,
|
||||||
@@ -347,11 +350,11 @@ impl<'ctx, 'id, 'ir, R: VmRuntimeCtx> DowngradeCtx<'ctx, 'id, 'ir, R> {
|
|||||||
impl<'ctx: 'ir, 'id, 'ir, R: VmRuntimeCtx> DowngradeContext<'id, 'ir>
|
impl<'ctx: 'ir, 'id, 'ir, R: VmRuntimeCtx> DowngradeContext<'id, 'ir>
|
||||||
for DowngradeCtx<'ctx, 'id, 'ir, R>
|
for DowngradeCtx<'ctx, 'id, 'ir, R>
|
||||||
{
|
{
|
||||||
fn new_expr(&self, expr: Ir<'ir, GhostRef<'id, 'ir>>) -> IrRef<'id, 'ir> {
|
fn new_expr(&self, expr: Ir<'ir, GhostRoRef<'id, 'ir>>) -> GhostRoIrRef<'id, 'ir> {
|
||||||
self.bump.alloc(GhostCell::new(expr))
|
self.bump.alloc(GhostCell::new(expr).into())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn maybe_thunk(&mut self, ir: IrRef<'id, 'ir>) -> GhostMaybeThunkRef<'id, 'ir> {
|
fn maybe_thunk(&mut self, ir: GhostRoIrRef<'id, 'ir>) -> GhostRoMaybeThunkRef<'id, 'ir> {
|
||||||
use MaybeThunk::*;
|
use MaybeThunk::*;
|
||||||
let expr = (|| {
|
let expr = (|| {
|
||||||
let expr = match *ir.borrow(&self.token) {
|
let expr = match *ir.borrow(&self.token) {
|
||||||
@@ -366,7 +369,7 @@ impl<'ctx: 'ir, 'id, 'ir, R: VmRuntimeCtx> DowngradeContext<'id, 'ir>
|
|||||||
Ir::MaybeThunk(thunk) => return Some(thunk),
|
Ir::MaybeThunk(thunk) => return Some(thunk),
|
||||||
_ => return None,
|
_ => return None,
|
||||||
};
|
};
|
||||||
Some(self.bump.alloc(GhostCell::new(expr)))
|
Some(self.bump.alloc(GhostCell::new(expr).into()))
|
||||||
})();
|
})();
|
||||||
if let Some(thunk) = expr {
|
if let Some(thunk) = expr {
|
||||||
return thunk;
|
return thunk;
|
||||||
@@ -376,8 +379,8 @@ impl<'ctx: 'ir, 'id, 'ir, R: VmRuntimeCtx> DowngradeContext<'id, 'ir>
|
|||||||
self.thunk_scopes
|
self.thunk_scopes
|
||||||
.last_mut()
|
.last_mut()
|
||||||
.expect("no active cache scope")
|
.expect("no active cache scope")
|
||||||
.add_binding(id, ir, &self.token);
|
.add_binding(id, ir);
|
||||||
self.bump.alloc(GhostCell::new(Thunk(id)))
|
self.bump.alloc(GhostCell::new(Thunk(id)).into())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn intern_string(&mut self, sym: impl AsRef<str>) -> StringId {
|
fn intern_string(&mut self, sym: impl AsRef<str>) -> StringId {
|
||||||
@@ -388,39 +391,35 @@ impl<'ctx: 'ir, 'id, 'ir, R: VmRuntimeCtx> DowngradeContext<'id, 'ir>
|
|||||||
self.runtime.resolve_string(id).into()
|
self.runtime.resolve_string(id).into()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn lookup(&self, sym: StringId, span: rnix::TextRange) -> Result<GhostMaybeThunkRef<'id, 'ir>> {
|
fn lookup(
|
||||||
|
&self,
|
||||||
|
sym: StringId,
|
||||||
|
span: rnix::TextRange,
|
||||||
|
) -> Result<GhostRoMaybeThunkRef<'id, 'ir>> {
|
||||||
for scope in self.scopes.iter().rev() {
|
for scope in self.scopes.iter().rev() {
|
||||||
match scope {
|
match scope {
|
||||||
&Scope::Global(global_scope) => {
|
&Scope::Global(global_scope) => {
|
||||||
use MaybeThunk::*;
|
|
||||||
if let Some(expr) = global_scope.get(&sym) {
|
if let Some(expr) = global_scope.get(&sym) {
|
||||||
let val = match expr {
|
return Ok(expr.into());
|
||||||
Ir::Builtins => Builtins,
|
|
||||||
Ir::Builtin(s) => Builtin(*s),
|
|
||||||
Ir::Bool(b) => Bool(*b),
|
|
||||||
Ir::Null => Null,
|
|
||||||
_ => unreachable!("globals should only contain leaf IR nodes"),
|
|
||||||
};
|
|
||||||
return Ok(self.bump.alloc(GhostCell::new(val)));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
&Scope::Repl(repl_bindings) => {
|
&Scope::Repl(repl_bindings) => {
|
||||||
if repl_bindings.contains(&sym) {
|
if repl_bindings.contains(&sym) {
|
||||||
return Ok(self
|
return Ok(self
|
||||||
.bump
|
.bump
|
||||||
.alloc(GhostCell::new(MaybeThunk::ReplBinding(sym))));
|
.alloc(GhostCell::new(MaybeThunk::ReplBinding(sym)).into()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Scope::ScopedImport(scoped_bindings) => {
|
Scope::ScopedImport(scoped_bindings) => {
|
||||||
if scoped_bindings.contains(&sym) {
|
if scoped_bindings.contains(&sym) {
|
||||||
return Ok(self
|
return Ok(self
|
||||||
.bump
|
.bump
|
||||||
.alloc(GhostCell::new(MaybeThunk::ScopedImportBinding(sym))));
|
.alloc(GhostCell::new(MaybeThunk::ScopedImportBinding(sym)).into()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Scope::Let(let_scope) => {
|
Scope::Let(let_scope) => {
|
||||||
if let Some(&expr) = let_scope.get(&sym) {
|
if let Some(&expr) = let_scope.get(&sym) {
|
||||||
return Ok(expr);
|
return Ok(expr.into());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
&Scope::Param {
|
&Scope::Param {
|
||||||
@@ -431,14 +430,18 @@ impl<'ctx: 'ir, 'id, 'ir, R: VmRuntimeCtx> DowngradeContext<'id, 'ir>
|
|||||||
let layers: u8 =
|
let layers: u8 =
|
||||||
self.thunk_scopes.len().try_into().expect("scope too deep!");
|
self.thunk_scopes.len().try_into().expect("scope too deep!");
|
||||||
let layer = layers - abs_layer;
|
let layer = layers - abs_layer;
|
||||||
return Ok(self.bump.alloc(GhostCell::new(MaybeThunk::Arg { layer })));
|
return Ok(self
|
||||||
|
.bump
|
||||||
|
.alloc(GhostCell::new(MaybeThunk::Arg { layer }).into()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.with_scope_count > 0 {
|
if self.with_scope_count > 0 {
|
||||||
Ok(self.bump.alloc(GhostCell::new(MaybeThunk::WithLookup(sym))))
|
Ok(self
|
||||||
|
.bump
|
||||||
|
.alloc(GhostCell::new(MaybeThunk::WithLookup(sym)).into()))
|
||||||
} else {
|
} else {
|
||||||
Err(Error::downgrade_error(
|
Err(Error::downgrade_error(
|
||||||
format!("'{}' not found", self.resolve_sym(sym)),
|
format!("'{}' not found", self.resolve_sym(sym)),
|
||||||
@@ -454,28 +457,40 @@ impl<'ctx: 'ir, 'id, 'ir, R: VmRuntimeCtx> DowngradeContext<'id, 'ir>
|
|||||||
|
|
||||||
fn with_let_scope<F, Ret>(&mut self, keys: &[StringId], f: F) -> Result<Ret>
|
fn with_let_scope<F, Ret>(&mut self, keys: &[StringId], f: F) -> Result<Ret>
|
||||||
where
|
where
|
||||||
F: FnOnce(&mut Self) -> Result<(bumpalo::collections::Vec<'ir, IrRef<'id, 'ir>>, Ret)>,
|
F: FnOnce(
|
||||||
|
&mut Self,
|
||||||
|
) -> Result<(
|
||||||
|
bumpalo::collections::Vec<'ir, GhostRoMaybeThunkRef<'id, 'ir>>,
|
||||||
|
Ret,
|
||||||
|
)>,
|
||||||
{
|
{
|
||||||
let base = *self.thunk_count;
|
let base = *self.thunk_count;
|
||||||
*self.thunk_count = self
|
*self.thunk_count = self
|
||||||
.thunk_count
|
.thunk_count
|
||||||
.checked_add(keys.len())
|
.checked_add(keys.len())
|
||||||
.expect("thunk id overflow");
|
.expect("thunk id overflow");
|
||||||
let scope = {
|
let handles = (base..base + keys.len())
|
||||||
let mut scope = HashMap::new();
|
.map(|id| {
|
||||||
for (offset, &key) in keys.iter().enumerate() {
|
&*self
|
||||||
scope.insert(key, &*self.bump.alloc(GhostCell::new(MaybeThunk::Thunk(ThunkId(base + offset)))));
|
.bump
|
||||||
}
|
.alloc(GhostCell::new(MaybeThunk::Thunk(ThunkId(id))))
|
||||||
scope
|
})
|
||||||
};
|
.collect::<Vec<_>>();
|
||||||
|
let scope = keys.iter().copied().zip(handles.iter().copied()).collect();
|
||||||
self.scopes.push(Scope::Let(scope));
|
self.scopes.push(Scope::Let(scope));
|
||||||
let (vals, ret) = {
|
let (vals, ret) = { f(self)? };
|
||||||
let mut guard = ScopeGuard { ctx: self };
|
self.scopes.pop();
|
||||||
f(guard.as_ctx())?
|
|
||||||
};
|
|
||||||
assert_eq!(keys.len(), vals.len());
|
assert_eq!(keys.len(), vals.len());
|
||||||
let scope = self.thunk_scopes.last_mut().expect("no active thunk scope");
|
let scope = self.thunk_scopes.last_mut().expect("no active thunk scope");
|
||||||
scope.extend_bindings((base..base + keys.len()).map(ThunkId).zip(vals));
|
for (i, (val, handle)) in vals.into_iter().zip(handles).enumerate() {
|
||||||
|
let thunk = *val.borrow(&self.token);
|
||||||
|
*handle.borrow_mut(&mut self.token) = thunk;
|
||||||
|
let id = ThunkId(base + i);
|
||||||
|
let ir_ref = self
|
||||||
|
.bump
|
||||||
|
.alloc(GhostCell::new(Ir::MaybeThunk(handle.into())).into());
|
||||||
|
scope.add_binding(id, ir_ref);
|
||||||
|
}
|
||||||
Ok(ret)
|
Ok(ret)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -506,7 +521,7 @@ impl<'ctx: 'ir, 'id, 'ir, R: VmRuntimeCtx> DowngradeContext<'id, 'ir>
|
|||||||
f: F,
|
f: F,
|
||||||
) -> (
|
) -> (
|
||||||
Ret,
|
Ret,
|
||||||
bumpalo::collections::Vec<'ir, (ThunkId, IrRef<'id, 'ir>)>,
|
bumpalo::collections::Vec<'ir, (ThunkId, GhostRoIrRef<'id, 'ir>)>,
|
||||||
)
|
)
|
||||||
where
|
where
|
||||||
F: FnOnce(&mut Self) -> Ret,
|
F: FnOnce(&mut Self) -> Ret,
|
||||||
@@ -546,7 +561,7 @@ impl<'id, 'ir, 'ctx: 'ir, R: VmRuntimeCtx> DowngradeCtx<'ctx, 'id, 'ir, R> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct ThunkScope<'id, 'ir> {
|
struct ThunkScope<'id, 'ir> {
|
||||||
bindings: bumpalo::collections::Vec<'ir, (ThunkId, IrRef<'id, 'ir>)>,
|
bindings: bumpalo::collections::Vec<'ir, (ThunkId, GhostRoIrRef<'id, 'ir>)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'id, 'ir> ThunkScope<'id, 'ir> {
|
impl<'id, 'ir> ThunkScope<'id, 'ir> {
|
||||||
@@ -556,17 +571,20 @@ impl<'id, 'ir> ThunkScope<'id, 'ir> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_binding(&mut self, id: ThunkId, ir: IrRef<'id, 'ir>, _token: &GhostToken<'id>) {
|
fn add_binding(&mut self, id: ThunkId, ir: GhostRoIrRef<'id, 'ir>) {
|
||||||
self.bindings.push((id, ir));
|
self.bindings.push((id, ir));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn extend_bindings(&mut self, iter: impl IntoIterator<Item = (ThunkId, IrRef<'id, 'ir>)>) {
|
fn extend_bindings(
|
||||||
|
&mut self,
|
||||||
|
iter: impl IntoIterator<Item = (ThunkId, GhostRoIrRef<'id, 'ir>)>,
|
||||||
|
) {
|
||||||
self.bindings.extend(iter);
|
self.bindings.extend(iter);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
enum Scope<'ctx, 'id, 'ir> {
|
enum Scope<'ctx, 'id, 'ir> {
|
||||||
Global(&'ctx HashMap<StringId, Ir<'static, RawRef<'static>>>),
|
Global(&'ctx HashMap<StringId, MaybeThunk>),
|
||||||
Repl(&'ctx HashSet<StringId>),
|
Repl(&'ctx HashSet<StringId>),
|
||||||
ScopedImport(HashSet<StringId>),
|
ScopedImport(HashSet<StringId>),
|
||||||
Let(HashMap<StringId, GhostMaybeThunkRef<'id, 'ir>>),
|
Let(HashMap<StringId, GhostMaybeThunkRef<'id, 'ir>>),
|
||||||
|
|||||||
Reference in New Issue
Block a user