feat: ir env (WIP)
This commit is contained in:
7
Cargo.lock
generated
7
Cargo.lock
generated
@@ -334,6 +334,7 @@ dependencies = [
|
||||
"inkwell",
|
||||
"itertools",
|
||||
"regex",
|
||||
"replace_with",
|
||||
"rnix",
|
||||
"rpds",
|
||||
"rustyline",
|
||||
@@ -409,6 +410,12 @@ version = "0.8.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c"
|
||||
|
||||
[[package]]
|
||||
name = "replace_with"
|
||||
version = "0.1.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "51743d3e274e2b18df81c4dc6caf8a5b8e15dbe799e0dca05c7617380094e884"
|
||||
|
||||
[[package]]
|
||||
name = "rnix"
|
||||
version = "0.12.0"
|
||||
|
||||
@@ -30,5 +30,6 @@ regex = "1.11"
|
||||
hashbrown = "0.15"
|
||||
inkwell = { version = "0.6.0", features = ["llvm18-1"] }
|
||||
gc-arena = { git = "https://github.com/kyren/gc-arena", rev = "d651e3b4363d525a2d502c2305bc73e291835c84", features= ["hashbrown"] }
|
||||
replace_with = "0.1"
|
||||
|
||||
rustyline = { version = "15.0", optional = true }
|
||||
|
||||
@@ -1,11 +1,16 @@
|
||||
use gc_arena::{Gc, Mutation};
|
||||
use hashbrown::HashMap;
|
||||
|
||||
use crate::env::VmEnv;
|
||||
use crate::env::{IrEnv, VmEnv};
|
||||
use crate::ty::internal::{AttrSet, CoW, PrimOp, Value};
|
||||
use crate::vm::VM;
|
||||
|
||||
pub fn env<'gc>(vm: &VM, mc: &Mutation<'gc>) -> Gc<'gc, VmEnv<'gc>> {
|
||||
pub fn ir_env<'gc>(mc: &Mutation<'gc>) -> Gc<'gc, IrEnv<'gc>> {
|
||||
// TODO:
|
||||
IrEnv::new(Gc::new(mc, HashMap::new()), mc)
|
||||
}
|
||||
|
||||
pub fn vm_env<'gc>(vm: &VM, mc: &Mutation<'gc>) -> Gc<'gc, VmEnv<'gc>> {
|
||||
let primops = [
|
||||
PrimOp::new("add", 2, |args, _, mc| {
|
||||
let Ok([mut first, second]): Result<[Value; 2], _> = args.try_into() else {
|
||||
|
||||
17
src/env.rs
17
src/env.rs
@@ -3,7 +3,7 @@ use std::hash::Hash;
|
||||
use gc_arena::{Collect, Gc, Mutation};
|
||||
use hashbrown::HashMap;
|
||||
|
||||
use crate::ty::internal::Value;
|
||||
use crate::{ir::Ir, ty::internal::Value};
|
||||
|
||||
#[derive(Collect)]
|
||||
#[collect(no_drop)]
|
||||
@@ -21,6 +21,7 @@ pub struct LetEnv<'gc, K: Hash + Eq + Collect<'gc>, V: Collect<'gc>> {
|
||||
}
|
||||
|
||||
pub type VmEnv<'gc> = Env<'gc, usize, Value<'gc>>;
|
||||
pub type IrEnv<'gc> = Env<'gc, usize, Ir>;
|
||||
|
||||
#[derive(Default, Clone, Collect)]
|
||||
#[collect(no_drop)]
|
||||
@@ -62,13 +63,25 @@ impl<'gc, K: Hash + Eq + Clone + Collect<'gc>, V: Clone + Collect<'gc>> Env<'gc,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn lookup(&self, symbol: &K) -> Option<&V> {
|
||||
pub fn lookup_slow(&self, symbol: &K) -> Option<&V> {
|
||||
if let Some(val) = self.let_.lookup(symbol) {
|
||||
return Some(val);
|
||||
}
|
||||
self.with.lookup(symbol)
|
||||
}
|
||||
|
||||
pub fn lookup_let(&self, symbol: &K) -> Option<&V> {
|
||||
self.let_.lookup(symbol)
|
||||
}
|
||||
|
||||
pub fn lookup_with(&self, symbol: &K) -> Option<&V> {
|
||||
self.with.lookup(symbol)
|
||||
}
|
||||
|
||||
pub fn has_with(&self) -> bool {
|
||||
self.with.map.is_some()
|
||||
}
|
||||
|
||||
pub fn enter_arg(self: Gc<'gc, Self>, ident: K, val: V, mc: &Mutation<'gc>) -> Gc<'gc, Self> {
|
||||
Gc::new(
|
||||
mc,
|
||||
|
||||
603
src/ir.rs
603
src/ir.rs
@@ -1,32 +1,36 @@
|
||||
use derive_more::IsVariant;
|
||||
use derive_more::{IsVariant, TryUnwrap, Unwrap};
|
||||
use gc_arena::{Arena, Collect, Gc, Mutation, Rootable};
|
||||
use hashbrown::HashMap;
|
||||
|
||||
use ecow::EcoString;
|
||||
use replace_with::{replace_with, replace_with_or_abort};
|
||||
use rnix::ast::{self, Expr};
|
||||
|
||||
use crate::builtins::ir_env;
|
||||
use crate::compile::*;
|
||||
use crate::env::IrEnv;
|
||||
use crate::error::*;
|
||||
use crate::ty::common as c;
|
||||
|
||||
pub fn downgrade(expr: Expr) -> Result<Downgraded> {
|
||||
let mut ctx = DowngradeContext::new();
|
||||
let ir = expr.downgrade(&mut ctx)?;
|
||||
let mut arena: Arena<Rootable![DowngradeContext<'_>]> =
|
||||
Arena::new(|mc| DowngradeContext::new(mc));
|
||||
arena.mutate_root(|mc, ctx| {
|
||||
let ir = expr.downgrade(ctx, mc)?;
|
||||
let consts = std::mem::take(&mut ctx.consts).into();
|
||||
let symbols = std::mem::take(&mut ctx.symbols);
|
||||
let symmap = std::mem::take(&mut ctx.symmap);
|
||||
let thunks = std::mem::take(&mut ctx.thunks).into();
|
||||
let funcs = std::mem::take(&mut ctx.funcs).into();
|
||||
Ok(Downgraded {
|
||||
top_level: ir,
|
||||
consts: ctx.consts.into(),
|
||||
symbols: ctx.symbols,
|
||||
symmap: ctx.symmap,
|
||||
thunks: ctx.thunks.into(),
|
||||
funcs: ctx.funcs.into(),
|
||||
consts,
|
||||
symbols,
|
||||
symmap,
|
||||
thunks,
|
||||
funcs,
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
trait Downcast<T: Sized>
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
fn downcast_ref(&self) -> Option<&T>;
|
||||
fn downcast_mut(&mut self) -> Option<&mut T>;
|
||||
}
|
||||
|
||||
macro_rules! ir {
|
||||
@@ -39,22 +43,55 @@ macro_rules! ir {
|
||||
)
|
||||
,*$(,)?
|
||||
) => {
|
||||
#[derive(Clone, Debug, IsVariant)]
|
||||
#[derive(Clone, Debug, IsVariant, Unwrap, Collect)]
|
||||
#[collect(require_static)]
|
||||
pub enum Ir {
|
||||
$(
|
||||
$ty($ty),
|
||||
)*
|
||||
}
|
||||
|
||||
#[derive(Debug, IsVariant, TryUnwrap)]
|
||||
pub enum IrRef<'a> {
|
||||
$(
|
||||
$ty(&'a $ty),
|
||||
)*
|
||||
}
|
||||
|
||||
#[derive(Debug, IsVariant, TryUnwrap)]
|
||||
pub enum IrMut<'a> {
|
||||
$(
|
||||
$ty(&'a mut $ty),
|
||||
)*
|
||||
}
|
||||
|
||||
impl Ir {
|
||||
fn boxed(self) -> Box<Self> {
|
||||
Box::new(self)
|
||||
}
|
||||
|
||||
fn ok(self) -> Result<Self> {
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
fn as_ref(&self) -> IrRef {
|
||||
match self {
|
||||
$(Ir::$ty(ir) => IrRef::$ty(ir),)*
|
||||
}
|
||||
}
|
||||
|
||||
fn as_mut(&mut self) -> IrMut {
|
||||
match self {
|
||||
$(Ir::$ty(ir) => IrMut::$ty(ir),)*
|
||||
}
|
||||
}
|
||||
|
||||
fn resolve<'gc>(self, ctx: &mut DowngradeContext<'gc>, mc: &Mutation<'gc>) -> Result<Ir> {
|
||||
match self {
|
||||
$(Ir::$ty(ir) => ir.resolve(ctx, mc),)*
|
||||
}
|
||||
}
|
||||
}
|
||||
impl Compile for Ir {
|
||||
fn compile(self, ctx: &mut Compiler) {
|
||||
match self {
|
||||
@@ -67,7 +104,8 @@ macro_rules! ir {
|
||||
$(
|
||||
#[$($x)*]
|
||||
)*
|
||||
#[derive(Clone, Debug)]
|
||||
#[derive(Clone, Debug, Collect)]
|
||||
#[collect(no_drop)]
|
||||
pub struct $ty {
|
||||
$(
|
||||
pub $name : $elemtype,
|
||||
@@ -79,21 +117,6 @@ macro_rules! ir {
|
||||
Ir::$ty(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl Downcast<$ty> for Ir {
|
||||
fn downcast_ref(&self) -> Option<&$ty> {
|
||||
match self {
|
||||
Ir::$ty(value) => Some(value),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
fn downcast_mut(&mut self) -> Option<&mut $ty> {
|
||||
match self {
|
||||
Ir::$ty(value) => Some(value),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
)*
|
||||
}
|
||||
}
|
||||
@@ -120,17 +143,38 @@ ir! {
|
||||
Path => { expr: Box<Ir> },
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
#[derive(Clone, Debug, Collect)]
|
||||
#[collect(require_static)]
|
||||
pub struct DynamicAttrPair(pub Ir, pub Ir);
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct DowngradeContext {
|
||||
pub struct DowngradeContext<'gc> {
|
||||
thunks: Vec<Ir>,
|
||||
funcs: Vec<Func>,
|
||||
consts: Vec<c::Const>,
|
||||
constmap: HashMap<c::Const, usize>,
|
||||
symbols: Vec<EcoString>,
|
||||
symmap: HashMap<EcoString, usize>,
|
||||
env: Gc<'gc, IrEnv<'gc>>,
|
||||
}
|
||||
|
||||
unsafe impl<'gc> Collect<'gc> for DowngradeContext<'gc> {
|
||||
fn trace<T: gc_arena::collect::Trace<'gc>>(&self, cc: &mut T) {
|
||||
self.env.trace(cc);
|
||||
}
|
||||
}
|
||||
|
||||
impl<'gc> DowngradeContext<'gc> {
|
||||
fn new(mc: &Mutation<'gc>) -> Self {
|
||||
DowngradeContext {
|
||||
thunks: Vec::default(),
|
||||
funcs: Vec::default(),
|
||||
consts: Vec::default(),
|
||||
constmap: HashMap::default(),
|
||||
symbols: Vec::default(),
|
||||
symmap: HashMap::default(),
|
||||
env: ir_env(mc),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Downgraded {
|
||||
@@ -142,11 +186,7 @@ pub struct Downgraded {
|
||||
pub funcs: Box<[Func]>,
|
||||
}
|
||||
|
||||
impl DowngradeContext {
|
||||
fn new() -> DowngradeContext {
|
||||
DowngradeContext::default()
|
||||
}
|
||||
|
||||
impl<'gc> DowngradeContext<'gc> {
|
||||
fn new_thunk(&mut self, thunk: Ir) -> Thunk {
|
||||
let idx = self.thunks.len();
|
||||
self.thunks.push(thunk);
|
||||
@@ -181,6 +221,50 @@ impl DowngradeContext {
|
||||
self.symbols.len() - 1
|
||||
}
|
||||
}
|
||||
|
||||
fn enter_arg(&mut self, ident: usize, val: Ir, mc: &Mutation<'gc>) {
|
||||
self.env = self.env.enter_arg(ident, val, mc)
|
||||
}
|
||||
|
||||
fn enter_let(&mut self, attrs: HashMap<usize, Ir>, mc: &Mutation<'gc>) {
|
||||
self.env = self.env.enter_let(Gc::new(mc, attrs), mc)
|
||||
}
|
||||
|
||||
fn enter_with(&mut self, attrs: HashMap<usize, Ir>, mc: &Mutation<'gc>) {
|
||||
self.env = self.env.enter_with(Gc::new(mc, attrs), mc)
|
||||
}
|
||||
|
||||
fn leave(&mut self) {
|
||||
self.env = self.env.leave()
|
||||
}
|
||||
|
||||
fn lookup(&self, ident: usize) -> Result<Option<&Ir>> {
|
||||
self.env.lookup_let(&ident).map_or_else(
|
||||
|| {
|
||||
Err(Error::DowngradeError(format!(
|
||||
"{} not found",
|
||||
&self.symbols[ident]
|
||||
)))
|
||||
},
|
||||
|val| Ok(Some(val)),
|
||||
)
|
||||
}
|
||||
|
||||
fn resolve_func(&mut self, idx: usize) -> Result<()> {
|
||||
self.funcs.get_mut(idx).map_or_else(|| unreachable!(), |func| {
|
||||
*func = func.resolve()?;
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
|
||||
fn resolve_thunk(&mut self, idx: usize, mc: &Mutation<'gc>) -> Result<()> {
|
||||
self.thunks.get_mut(idx).map_or_else(|| unreachable!(), |thunk| {
|
||||
replace_with_or_abort(thunk, |thunk| {
|
||||
thunk.resolve(self, mc)
|
||||
});
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl Attrs {
|
||||
@@ -192,11 +276,12 @@ impl Attrs {
|
||||
self.stcs
|
||||
.get_mut(&ident)
|
||||
.unwrap()
|
||||
.downcast_mut()
|
||||
.ok_or_else(|| {
|
||||
Error::DowngradeError(format!(
|
||||
.as_mut()
|
||||
.try_unwrap_attrs()
|
||||
.or_else(|_| {
|
||||
Err(Error::DowngradeError(format!(
|
||||
r#""{ident}" already exsists in this set"#
|
||||
))
|
||||
)))
|
||||
})
|
||||
.and_then(|attrs: &mut Attrs| attrs._insert(path, name, value))
|
||||
} else {
|
||||
@@ -263,7 +348,7 @@ impl Attrs {
|
||||
Some(Attr::Str(ident)) => self
|
||||
.stcs
|
||||
.get(ident)
|
||||
.and_then(|attrs| attrs.downcast_ref())
|
||||
.and_then(|attrs| attrs.as_ref().try_unwrap_attrs().ok())
|
||||
.map_or(Some(false), |attrs: &Attrs| attrs._has_attr(path, name)),
|
||||
None => match name {
|
||||
Attr::Str(ident) => Some(self.stcs.get(&ident).is_some()),
|
||||
@@ -280,14 +365,32 @@ impl Attrs {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
#[derive(Clone, Debug, Collect)]
|
||||
#[collect(require_static)]
|
||||
pub enum Attr {
|
||||
Dynamic(Ir),
|
||||
Strs(ConcatStrings),
|
||||
Str(usize),
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
impl Attr {
|
||||
fn resolve<'gc>(self, ctx: &mut DowngradeContext<'gc>, mc: &Mutation<'gc>) -> Result<Attr> {
|
||||
use Attr::*;
|
||||
Ok(match self {
|
||||
Dynamic(ir) => Dynamic(ir.resolve(ctx, mc)?),
|
||||
other => other
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl Thunk {
|
||||
fn resolve<'gc>(self, ctx: &mut DowngradeContext<'gc>, mc: &Mutation<'gc>) -> Result<Attr> {
|
||||
ctx.enter_with(attrs, mc);
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Collect)]
|
||||
#[collect(require_static)]
|
||||
pub enum BinOpKind {
|
||||
Add,
|
||||
Sub,
|
||||
@@ -336,7 +439,8 @@ impl From<ast::BinOpKind> for BinOpKind {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
#[derive(Clone, Debug, Collect)]
|
||||
#[collect(require_static)]
|
||||
pub enum UnOpKind {
|
||||
Neg,
|
||||
Not,
|
||||
@@ -351,12 +455,15 @@ impl From<ast::UnaryOpKind> for UnOpKind {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Collect)]
|
||||
#[collect(no_drop)]
|
||||
pub struct Func {
|
||||
pub param: Param,
|
||||
pub body: Box<Ir>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
#[derive(Clone, Debug, Collect)]
|
||||
#[collect(no_drop)]
|
||||
pub enum Param {
|
||||
Ident(usize),
|
||||
Formals {
|
||||
@@ -370,41 +477,52 @@ trait Downgrade
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
fn downgrade(self, ctx: &mut DowngradeContext) -> Result<Ir>;
|
||||
fn downgrade<'gc>(self, ctx: &mut DowngradeContext<'gc>, mc: &Mutation<'gc>) -> Result<Ir>;
|
||||
}
|
||||
|
||||
impl Downgrade for Expr {
|
||||
fn downgrade(self, ctx: &mut DowngradeContext) -> Result<Ir> {
|
||||
fn downgrade<'gc>(self, ctx: &mut DowngradeContext<'gc>, mc: &Mutation<'gc>) -> Result<Ir> {
|
||||
match self {
|
||||
Expr::Apply(apply) => apply.downgrade(ctx),
|
||||
Expr::Assert(assert) => assert.downgrade(ctx),
|
||||
Expr::Apply(apply) => apply.downgrade(ctx, mc),
|
||||
Expr::Assert(assert) => assert.downgrade(ctx, mc),
|
||||
Expr::Error(error) => Err(Error::DowngradeError(error.to_string())),
|
||||
Expr::IfElse(ifelse) => ifelse.downgrade(ctx),
|
||||
Expr::Select(select) => select.downgrade(ctx),
|
||||
Expr::Str(str) => str.downgrade(ctx),
|
||||
Expr::Path(path) => path.downgrade(ctx),
|
||||
Expr::Literal(lit) => lit.downgrade(ctx),
|
||||
Expr::Lambda(lambda) => lambda.downgrade(ctx),
|
||||
Expr::LegacyLet(let_) => let_.downgrade(ctx),
|
||||
Expr::LetIn(letin) => letin.downgrade(ctx),
|
||||
Expr::List(list) => list.downgrade(ctx),
|
||||
Expr::BinOp(op) => op.downgrade(ctx),
|
||||
Expr::Paren(paren) => paren.expr().unwrap().downgrade(ctx),
|
||||
Expr::Root(root) => root.expr().unwrap().downgrade(ctx),
|
||||
Expr::AttrSet(attrs) => attrs.downgrade(ctx),
|
||||
Expr::UnaryOp(op) => op.downgrade(ctx),
|
||||
Expr::Ident(ident) => ident.downgrade(ctx),
|
||||
Expr::With(with) => with.downgrade(ctx),
|
||||
Expr::HasAttr(has) => has.downgrade(ctx),
|
||||
Expr::IfElse(ifelse) => ifelse.downgrade(ctx, mc),
|
||||
Expr::Select(select) => select.downgrade(ctx, mc),
|
||||
Expr::Str(str) => str.downgrade(ctx, mc),
|
||||
Expr::Path(path) => path.downgrade(ctx, mc),
|
||||
Expr::Literal(lit) => lit.downgrade(ctx, mc),
|
||||
Expr::Lambda(lambda) => lambda.downgrade(ctx, mc),
|
||||
Expr::LegacyLet(let_) => let_.downgrade(ctx, mc),
|
||||
Expr::LetIn(letin) => letin.downgrade(ctx, mc),
|
||||
Expr::List(list) => list.downgrade(ctx, mc),
|
||||
Expr::BinOp(op) => op.downgrade(ctx, mc),
|
||||
Expr::Paren(paren) => paren.expr().unwrap().downgrade(ctx, mc),
|
||||
Expr::Root(root) => root.expr().unwrap().downgrade(ctx, mc),
|
||||
Expr::AttrSet(attrs) => attrs.downgrade(ctx, mc),
|
||||
Expr::UnaryOp(op) => op.downgrade(ctx, mc),
|
||||
Expr::Ident(ident) => ident.downgrade(ctx, mc),
|
||||
Expr::With(with) => with.downgrade(ctx, mc),
|
||||
Expr::HasAttr(has) => has.downgrade(ctx, mc),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Downgrade for ast::Assert {
|
||||
fn downgrade(self, ctx: &mut DowngradeContext) -> Result<Ir> {
|
||||
fn downgrade<'gc>(self, ctx: &mut DowngradeContext<'gc>, mc: &Mutation<'gc>) -> Result<Ir> {
|
||||
Assert {
|
||||
assertion: self.condition().unwrap().downgrade(ctx)?.boxed(),
|
||||
expr: self.body().unwrap().downgrade(ctx)?.boxed(),
|
||||
assertion: self.condition().unwrap().downgrade(ctx, mc)?.boxed(),
|
||||
expr: self.body().unwrap().downgrade(ctx, mc)?.boxed(),
|
||||
}
|
||||
.ir()
|
||||
.ok()
|
||||
}
|
||||
}
|
||||
|
||||
impl Assert {
|
||||
fn resolve<'gc>(self, ctx: &mut DowngradeContext<'gc>, mc: &Mutation<'gc>) -> Result<Ir> {
|
||||
Self {
|
||||
assertion: self.assertion.resolve(ctx, mc)?.boxed(),
|
||||
expr: self.expr.resolve(ctx, mc)?.boxed(),
|
||||
}
|
||||
.ir()
|
||||
.ok()
|
||||
@@ -412,11 +530,23 @@ impl Downgrade for ast::Assert {
|
||||
}
|
||||
|
||||
impl Downgrade for ast::IfElse {
|
||||
fn downgrade(self, ctx: &mut DowngradeContext) -> Result<Ir> {
|
||||
fn downgrade<'gc>(self, ctx: &mut DowngradeContext<'gc>, mc: &Mutation<'gc>) -> Result<Ir> {
|
||||
If {
|
||||
cond: self.condition().unwrap().downgrade(ctx)?.boxed(),
|
||||
consq: self.body().unwrap().downgrade(ctx)?.boxed(),
|
||||
alter: self.else_body().unwrap().downgrade(ctx)?.boxed(),
|
||||
cond: self.condition().unwrap().downgrade(ctx, mc)?.boxed(),
|
||||
consq: self.body().unwrap().downgrade(ctx, mc)?.boxed(),
|
||||
alter: self.else_body().unwrap().downgrade(ctx, mc)?.boxed(),
|
||||
}
|
||||
.ir()
|
||||
.ok()
|
||||
}
|
||||
}
|
||||
|
||||
impl If {
|
||||
fn resolve<'gc>(self, ctx: &mut DowngradeContext<'gc>, mc: &Mutation<'gc>) -> Result<Ir> {
|
||||
If {
|
||||
cond: self.cond.resolve(ctx, mc)?.boxed(),
|
||||
consq: self.consq.resolve(ctx, mc)?.boxed(),
|
||||
alter: self.alter.resolve(ctx, mc)?.boxed(),
|
||||
}
|
||||
.ir()
|
||||
.ok()
|
||||
@@ -424,13 +554,13 @@ impl Downgrade for ast::IfElse {
|
||||
}
|
||||
|
||||
impl Downgrade for ast::Path {
|
||||
fn downgrade(self, ctx: &mut DowngradeContext) -> Result<Ir> {
|
||||
fn downgrade<'gc>(self, ctx: &mut DowngradeContext<'gc>, mc: &Mutation<'gc>) -> Result<Ir> {
|
||||
let parts = self
|
||||
.parts()
|
||||
.map(|part| match part {
|
||||
ast::InterpolPart::Literal(lit) => ctx.new_const(lit.to_string().into()).ir().ok(),
|
||||
ast::InterpolPart::Interpolation(interpol) => {
|
||||
interpol.expr().unwrap().downgrade(ctx)
|
||||
interpol.expr().unwrap().downgrade(ctx, mc)
|
||||
}
|
||||
})
|
||||
.collect::<Result<Vec<_>>>()?;
|
||||
@@ -448,15 +578,25 @@ impl Downgrade for ast::Path {
|
||||
}
|
||||
}
|
||||
|
||||
impl Path {
|
||||
fn resolve<'gc>(self, ctx: &mut DowngradeContext<'gc>, mc: &Mutation<'gc>) -> Result<Ir> {
|
||||
Self {
|
||||
expr: self.expr.resolve(ctx, mc)?.boxed(),
|
||||
}
|
||||
.ir()
|
||||
.ok()
|
||||
}
|
||||
}
|
||||
|
||||
impl Downgrade for ast::Str {
|
||||
fn downgrade(self, ctx: &mut DowngradeContext) -> Result<Ir> {
|
||||
fn downgrade<'gc>(self, ctx: &mut DowngradeContext<'gc>, mc: &Mutation<'gc>) -> Result<Ir> {
|
||||
let parts = self
|
||||
.normalized_parts()
|
||||
.into_iter()
|
||||
.map(|part| match part {
|
||||
ast::InterpolPart::Literal(lit) => ctx.new_const(lit.into()).ir().ok(),
|
||||
ast::InterpolPart::Interpolation(interpol) => {
|
||||
interpol.expr().unwrap().downgrade(ctx)
|
||||
interpol.expr().unwrap().downgrade(ctx, mc)
|
||||
}
|
||||
})
|
||||
.collect::<Result<Vec<_>>>()?;
|
||||
@@ -468,8 +608,22 @@ impl Downgrade for ast::Str {
|
||||
}
|
||||
}
|
||||
|
||||
impl ConcatStrings {
|
||||
fn resolve<'gc>(self, ctx: &mut DowngradeContext<'gc>, mc: &Mutation<'gc>) -> Result<Ir> {
|
||||
Self {
|
||||
parts: self
|
||||
.parts
|
||||
.into_iter()
|
||||
.map(|ir| ir.resolve(ctx, mc))
|
||||
.collect::<Result<Vec<_>>>()?,
|
||||
}
|
||||
.ir()
|
||||
.ok()
|
||||
}
|
||||
}
|
||||
|
||||
impl Downgrade for ast::Literal {
|
||||
fn downgrade(self, ctx: &mut DowngradeContext) -> Result<Ir> {
|
||||
fn downgrade<'gc>(self, ctx: &mut DowngradeContext<'gc>, _: &Mutation<'gc>) -> Result<Ir> {
|
||||
match self.kind() {
|
||||
ast::LiteralKind::Integer(int) => ctx.new_const(int.value().unwrap().into()),
|
||||
ast::LiteralKind::Float(float) => ctx.new_const(float.value().unwrap().into()),
|
||||
@@ -480,38 +634,88 @@ impl Downgrade for ast::Literal {
|
||||
}
|
||||
}
|
||||
|
||||
impl Const {
|
||||
fn resolve<'gc>(self, ctx: &mut DowngradeContext<'gc>, mc: &Mutation<'gc>) -> Result<Ir> {
|
||||
self.ir().ok()
|
||||
}
|
||||
}
|
||||
|
||||
impl Downgrade for ast::Ident {
|
||||
fn downgrade(self, ctx: &mut DowngradeContext) -> Result<Ir> {
|
||||
Var {
|
||||
sym: ctx.new_sym(self.to_string()),
|
||||
fn downgrade<'gc>(self, ctx: &mut DowngradeContext<'gc>, _: &Mutation<'gc>) -> Result<Ir> {
|
||||
let sym = ctx.new_sym(self.ident_token().unwrap().text());
|
||||
Var { sym }.ir().ok()
|
||||
}
|
||||
}
|
||||
|
||||
impl Var {
|
||||
fn resolve<'gc>(self, ctx: &mut DowngradeContext<'gc>, mc: &Mutation<'gc>) -> Result<Ir> {
|
||||
ctx.lookup(self.sym)?
|
||||
.map_or(Var { ..self }.ir().ok(), |val| val.clone().ok())
|
||||
}
|
||||
}
|
||||
|
||||
impl Downgrade for ast::AttrSet {
|
||||
fn downgrade<'gc>(self, ctx: &mut DowngradeContext<'gc>, mc: &Mutation<'gc>) -> Result<Ir> {
|
||||
let rec = self.rec_token().is_some();
|
||||
downgrade_has_entry(self, rec, ctx, mc).map(|attrs| attrs.ir())
|
||||
}
|
||||
}
|
||||
|
||||
impl Attrs {
|
||||
fn resolve<'gc>(self, ctx: &mut DowngradeContext<'gc>, mc: &Mutation<'gc>) -> Result<Ir> {
|
||||
if self.rec {
|
||||
todo!()
|
||||
} else {
|
||||
Self {
|
||||
stcs: self
|
||||
.stcs
|
||||
.into_iter()
|
||||
.map(|(k, v)| Ok((k, v.resolve(ctx, mc)?)))
|
||||
.collect::<Result<_>>()?,
|
||||
dyns: self
|
||||
.dyns
|
||||
.into_iter()
|
||||
.map(|DynamicAttrPair(k, v)| {
|
||||
Ok(DynamicAttrPair(k.resolve(ctx, mc)?, v.resolve(ctx, mc)?))
|
||||
})
|
||||
.collect::<Result<_>>()?,
|
||||
rec: false,
|
||||
}
|
||||
}
|
||||
.ir()
|
||||
.ok()
|
||||
}
|
||||
}
|
||||
|
||||
impl Downgrade for ast::AttrSet {
|
||||
fn downgrade(self, ctx: &mut DowngradeContext) -> Result<Ir> {
|
||||
let rec = self.rec_token().is_some();
|
||||
downgrade_has_entry(self, rec, ctx).map(|attrs| attrs.ir())
|
||||
}
|
||||
}
|
||||
|
||||
impl Downgrade for ast::List {
|
||||
fn downgrade(self, ctx: &mut DowngradeContext) -> Result<Ir> {
|
||||
fn downgrade<'gc>(self, ctx: &mut DowngradeContext<'gc>, mc: &Mutation<'gc>) -> Result<Ir> {
|
||||
let mut items = Vec::with_capacity(self.items().size_hint().0);
|
||||
for item in self.items() {
|
||||
items.push(item.downgrade(ctx)?)
|
||||
items.push(item.downgrade(ctx, mc)?)
|
||||
}
|
||||
List { items }.ir().ok()
|
||||
}
|
||||
}
|
||||
|
||||
impl List {
|
||||
fn resolve<'gc>(self, ctx: &mut DowngradeContext<'gc>, mc: &Mutation<'gc>) -> Result<Ir> {
|
||||
Self {
|
||||
items: self
|
||||
.items
|
||||
.into_iter()
|
||||
.map(|item| item.resolve(ctx, mc))
|
||||
.collect::<Result<_>>()?,
|
||||
}
|
||||
.ir()
|
||||
.ok()
|
||||
}
|
||||
}
|
||||
|
||||
impl Downgrade for ast::BinOp {
|
||||
fn downgrade(self, ctx: &mut DowngradeContext) -> Result<Ir> {
|
||||
fn downgrade<'gc>(self, ctx: &mut DowngradeContext<'gc>, mc: &Mutation<'gc>) -> Result<Ir> {
|
||||
BinOp {
|
||||
lhs: self.lhs().unwrap().downgrade(ctx)?.boxed(),
|
||||
rhs: self.rhs().unwrap().downgrade(ctx)?.boxed(),
|
||||
lhs: self.lhs().unwrap().downgrade(ctx, mc)?.boxed(),
|
||||
rhs: self.rhs().unwrap().downgrade(ctx, mc)?.boxed(),
|
||||
kind: self.operator().unwrap().into(),
|
||||
}
|
||||
.ir()
|
||||
@@ -519,10 +723,22 @@ impl Downgrade for ast::BinOp {
|
||||
}
|
||||
}
|
||||
|
||||
impl BinOp {
|
||||
fn resolve<'gc>(self, ctx: &mut DowngradeContext<'gc>, mc: &Mutation<'gc>) -> Result<Ir> {
|
||||
Self {
|
||||
lhs: self.lhs.resolve(ctx, mc)?.boxed(),
|
||||
rhs: self.rhs.resolve(ctx, mc)?.boxed(),
|
||||
..self
|
||||
}
|
||||
.ir()
|
||||
.ok()
|
||||
}
|
||||
}
|
||||
|
||||
impl Downgrade for ast::HasAttr {
|
||||
fn downgrade(self, ctx: &mut DowngradeContext) -> Result<Ir> {
|
||||
let attrs = self.expr().unwrap().downgrade(ctx)?;
|
||||
let path = downgrade_attrpath(self.attrpath().unwrap(), ctx)?;
|
||||
fn downgrade<'gc>(self, ctx: &mut DowngradeContext<'gc>, mc: &Mutation<'gc>) -> Result<Ir> {
|
||||
let attrs = self.expr().unwrap().downgrade(ctx, mc)?;
|
||||
let path = downgrade_attrpath(self.attrpath().unwrap(), ctx, mc)?;
|
||||
HasAttr {
|
||||
lhs: attrs.boxed(),
|
||||
rhs: path,
|
||||
@@ -532,10 +748,21 @@ impl Downgrade for ast::HasAttr {
|
||||
}
|
||||
}
|
||||
|
||||
impl HasAttr {
|
||||
fn resolve<'gc>(self, ctx: &mut DowngradeContext<'gc>, mc: &Mutation<'gc>) -> Result<Ir> {
|
||||
Self {
|
||||
lhs: self.lhs.resolve(ctx, mc)?.boxed(),
|
||||
rhs: self.rhs.into_iter().map(|attr| attr.resolve(ctx, mc)).collect::<Result<_>>()?,
|
||||
}
|
||||
.ir()
|
||||
.ok()
|
||||
}
|
||||
}
|
||||
|
||||
impl Downgrade for ast::UnaryOp {
|
||||
fn downgrade(self, ctx: &mut DowngradeContext) -> Result<Ir> {
|
||||
fn downgrade<'gc>(self, ctx: &mut DowngradeContext<'gc>, mc: &Mutation<'gc>) -> Result<Ir> {
|
||||
UnOp {
|
||||
rhs: self.expr().unwrap().downgrade(ctx)?.boxed(),
|
||||
rhs: self.expr().unwrap().downgrade(ctx, mc)?.boxed(),
|
||||
kind: self.operator().unwrap().into(),
|
||||
}
|
||||
.ir()
|
||||
@@ -543,13 +770,24 @@ impl Downgrade for ast::UnaryOp {
|
||||
}
|
||||
}
|
||||
|
||||
impl UnOp {
|
||||
fn resolve<'gc>(self, ctx: &mut DowngradeContext<'gc>, mc: &Mutation<'gc>) -> Result<Ir> {
|
||||
Self {
|
||||
rhs: self.rhs.resolve(ctx, mc)?.boxed(),
|
||||
..self
|
||||
}
|
||||
.ir()
|
||||
.ok()
|
||||
}
|
||||
}
|
||||
|
||||
impl Downgrade for ast::Select {
|
||||
fn downgrade(self, ctx: &mut DowngradeContext) -> Result<Ir> {
|
||||
fn downgrade<'gc>(self, ctx: &mut DowngradeContext<'gc>, mc: &Mutation<'gc>) -> Result<Ir> {
|
||||
Select {
|
||||
expr: self.expr().unwrap().downgrade(ctx)?.boxed(),
|
||||
attrpath: downgrade_attrpath(self.attrpath().unwrap(), ctx)?,
|
||||
expr: self.expr().unwrap().downgrade(ctx, mc)?.boxed(),
|
||||
attrpath: downgrade_attrpath(self.attrpath().unwrap(), ctx, mc)?,
|
||||
default: match self.default_expr() {
|
||||
Some(default) => Some(default.downgrade(ctx)?.boxed()),
|
||||
Some(default) => Some(default.downgrade(ctx, mc)?.boxed()),
|
||||
None => None,
|
||||
},
|
||||
}
|
||||
@@ -558,12 +796,29 @@ impl Downgrade for ast::Select {
|
||||
}
|
||||
}
|
||||
|
||||
impl Select {
|
||||
fn resolve<'gc>(self, ctx: &mut DowngradeContext<'gc>, mc: &Mutation<'gc>) -> Result<Ir> {
|
||||
let default = if let Some(default) = self.default {
|
||||
Some(default.resolve(ctx, mc)?.boxed())
|
||||
} else {
|
||||
None
|
||||
};
|
||||
Self {
|
||||
expr: self.expr.resolve(ctx, mc)?.boxed(),
|
||||
attrpath: self.attrpath.into_iter().map(|attr| attr.resolve(ctx, mc)).collect::<Result<_>>()?,
|
||||
default
|
||||
}
|
||||
.ir()
|
||||
.ok()
|
||||
}
|
||||
}
|
||||
|
||||
impl Downgrade for ast::LegacyLet {
|
||||
fn downgrade(self, ctx: &mut DowngradeContext) -> Result<Ir> {
|
||||
let attrs = downgrade_has_entry(self, true, ctx)?;
|
||||
fn downgrade<'gc>(self, ctx: &mut DowngradeContext<'gc>, mc: &Mutation<'gc>) -> Result<Ir> {
|
||||
let attrs = downgrade_has_entry(self, true, ctx, mc)?;
|
||||
Select {
|
||||
expr: attrs.ir().boxed(),
|
||||
attrpath: vec![Attr::Str(ctx.new_sym("body".to_string()))],
|
||||
attrpath: vec![Attr::Str(ctx.new_sym("body"))],
|
||||
default: None,
|
||||
}
|
||||
.ir()
|
||||
@@ -572,59 +827,98 @@ impl Downgrade for ast::LegacyLet {
|
||||
}
|
||||
|
||||
impl Downgrade for ast::LetIn {
|
||||
fn downgrade(self, ctx: &mut DowngradeContext) -> Result<Ir> {
|
||||
fn downgrade<'gc>(self, ctx: &mut DowngradeContext<'gc>, mc: &Mutation<'gc>) -> Result<Ir> {
|
||||
let body = self.body().unwrap();
|
||||
let attrs = downgrade_has_entry(self, true, ctx)?;
|
||||
let expr = body.downgrade(ctx)?.boxed();
|
||||
let attrs = downgrade_has_entry(self, true, ctx, mc)?;
|
||||
let expr = body.downgrade(ctx, mc)?.boxed();
|
||||
Let { attrs, expr }.ir().ok()
|
||||
}
|
||||
}
|
||||
|
||||
impl Let {
|
||||
fn resolve<'gc>(self, ctx: &mut DowngradeContext<'gc>, mc: &Mutation<'gc>) -> Result<Ir> {
|
||||
let attrs = self.attrs.resolve(ctx, mc)?.unwrap_attrs();
|
||||
ctx.enter_let(attrs.stcs.clone(), mc);
|
||||
let expr = self.expr.resolve(ctx, mc)?.boxed();
|
||||
ctx.leave();
|
||||
|
||||
Self { attrs, expr }.ir().ok()
|
||||
}
|
||||
}
|
||||
|
||||
impl Downgrade for ast::With {
|
||||
fn downgrade(self, ctx: &mut DowngradeContext) -> Result<Ir> {
|
||||
let namespace = self.namespace().unwrap().downgrade(ctx)?;
|
||||
fn downgrade<'gc>(self, ctx: &mut DowngradeContext<'gc>, mc: &Mutation<'gc>) -> Result<Ir> {
|
||||
let namespace = self.namespace().unwrap().downgrade(ctx, mc)?;
|
||||
if let Ir::Attrs(attrs) = namespace {
|
||||
let expr = self.body().unwrap().downgrade(ctx)?.boxed();
|
||||
let expr = self.body().unwrap().downgrade(ctx, mc)?.boxed();
|
||||
Let { attrs, expr }.ir().ok()
|
||||
} else {
|
||||
let namespace = namespace.boxed();
|
||||
let expr = self.body().unwrap().downgrade(ctx)?.boxed();
|
||||
let expr = self.body().unwrap().downgrade(ctx, mc)?.boxed();
|
||||
With { namespace, expr }.ir().ok()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl With {
|
||||
fn resolve<'gc>(self, ctx: &mut DowngradeContext<'gc>, mc: &Mutation<'gc>) -> Result<Ir> {
|
||||
let namespace = self.namespace.resolve(ctx, mc)?.boxed();
|
||||
ctx.enter_with(HashMap::new(), mc);
|
||||
let expr = self.expr.resolve(ctx, mc)?.boxed();
|
||||
Self { namespace, expr }.ir().ok()
|
||||
}
|
||||
}
|
||||
|
||||
impl Downgrade for ast::Lambda {
|
||||
fn downgrade(self, ctx: &mut DowngradeContext) -> Result<Ir> {
|
||||
fn downgrade<'gc>(self, ctx: &mut DowngradeContext<'gc>, mc: &Mutation<'gc>) -> Result<Ir> {
|
||||
let body = self.body().unwrap();
|
||||
let param = downgrade_param(self.param().unwrap(), ctx)?;
|
||||
let body = body.downgrade(ctx)?.boxed();
|
||||
let param = downgrade_param(self.param().unwrap(), ctx, mc)?;
|
||||
let body = body.downgrade(ctx, mc)?.boxed();
|
||||
ctx.new_func(Func { param, body }).ir().ok()
|
||||
}
|
||||
}
|
||||
|
||||
impl Downgrade for ast::Apply {
|
||||
fn downgrade(self, ctx: &mut DowngradeContext) -> Result<Ir> {
|
||||
let mut args = vec![self.argument().unwrap().downgrade(ctx)?];
|
||||
fn downgrade<'gc>(self, ctx: &mut DowngradeContext<'gc>, mc: &Mutation<'gc>) -> Result<Ir> {
|
||||
let mut args = vec![self.argument().unwrap().downgrade(ctx, mc)?];
|
||||
let mut func = self.lambda().unwrap();
|
||||
while let ast::Expr::Apply(call) = func {
|
||||
func = call.lambda().unwrap();
|
||||
args.push(call.argument().unwrap().downgrade(ctx)?);
|
||||
args.push(call.argument().unwrap().downgrade(ctx, mc)?);
|
||||
}
|
||||
let func = func.downgrade(ctx)?.boxed();
|
||||
let func = func.downgrade(ctx, mc)?.boxed();
|
||||
args.reverse();
|
||||
Call { func, args }.ir().ok()
|
||||
}
|
||||
}
|
||||
|
||||
fn downgrade_param(param: ast::Param, ctx: &mut DowngradeContext) -> Result<Param> {
|
||||
match param {
|
||||
ast::Param::IdentParam(ident) => Ok(Param::Ident(ctx.new_sym(ident.to_string()))),
|
||||
ast::Param::Pattern(pattern) => downgrade_pattern(pattern, ctx),
|
||||
impl Call {
|
||||
fn resolve<'gc>(self, ctx: &mut DowngradeContext<'gc>, mc: &Mutation<'gc>) -> Result<Ir> {
|
||||
Self {
|
||||
func: self.func.resolve(ctx, mc)?.boxed(),
|
||||
args: self.args.into_iter().map(|arg| arg.resolve(ctx, mc)).collect::<Result<_>>()?,
|
||||
}
|
||||
.ir()
|
||||
.ok()
|
||||
}
|
||||
}
|
||||
|
||||
fn downgrade_pattern(pattern: ast::Pattern, ctx: &mut DowngradeContext) -> Result<Param> {
|
||||
fn downgrade_param<'gc>(
|
||||
param: ast::Param,
|
||||
ctx: &mut DowngradeContext<'gc>,
|
||||
mc: &Mutation<'gc>,
|
||||
) -> Result<Param> {
|
||||
match param {
|
||||
ast::Param::IdentParam(ident) => Ok(Param::Ident(ctx.new_sym(ident.to_string()))),
|
||||
ast::Param::Pattern(pattern) => downgrade_pattern(pattern, ctx, mc),
|
||||
}
|
||||
}
|
||||
|
||||
fn downgrade_pattern<'gc>(
|
||||
pattern: ast::Pattern,
|
||||
ctx: &mut DowngradeContext<'gc>,
|
||||
mc: &Mutation<'gc>,
|
||||
) -> Result<Param> {
|
||||
let formals = pattern
|
||||
.pat_entries()
|
||||
.map(|entry| {
|
||||
@@ -635,7 +929,7 @@ fn downgrade_pattern(pattern: ast::Pattern, ctx: &mut DowngradeContext) -> Resul
|
||||
entry
|
||||
.default()
|
||||
.unwrap()
|
||||
.downgrade(ctx)
|
||||
.downgrade(ctx, mc)
|
||||
.map(|ok| (ident, Some(ctx.new_thunk(ok))))
|
||||
}
|
||||
})
|
||||
@@ -651,10 +945,11 @@ fn downgrade_pattern(pattern: ast::Pattern, ctx: &mut DowngradeContext) -> Resul
|
||||
})
|
||||
}
|
||||
|
||||
fn downgrade_has_entry(
|
||||
fn downgrade_has_entry<'gc>(
|
||||
has_entry: impl ast::HasEntry,
|
||||
rec: bool,
|
||||
ctx: &mut DowngradeContext,
|
||||
ctx: &mut DowngradeContext<'gc>,
|
||||
mc: &Mutation<'gc>,
|
||||
) -> Result<Attrs> {
|
||||
let entires = has_entry.entries();
|
||||
let mut attrs = Attrs {
|
||||
@@ -665,27 +960,30 @@ fn downgrade_has_entry(
|
||||
|
||||
for entry in entires {
|
||||
match entry {
|
||||
ast::Entry::Inherit(inherit) => downgrade_inherit(inherit, &mut attrs.stcs, ctx)?,
|
||||
ast::Entry::AttrpathValue(value) => downgrade_attrpathvalue(value, &mut attrs, ctx)?,
|
||||
ast::Entry::Inherit(inherit) => downgrade_inherit(inherit, &mut attrs.stcs, ctx, mc)?,
|
||||
ast::Entry::AttrpathValue(value) => {
|
||||
downgrade_attrpathvalue(value, &mut attrs, ctx, mc)?
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(attrs)
|
||||
}
|
||||
|
||||
fn downgrade_inherit(
|
||||
fn downgrade_inherit<'gc>(
|
||||
inherit: ast::Inherit,
|
||||
stcs: &mut HashMap<usize, Ir>,
|
||||
ctx: &mut DowngradeContext,
|
||||
ctx: &mut DowngradeContext<'gc>,
|
||||
mc: &Mutation<'gc>,
|
||||
) -> Result<()> {
|
||||
let from = if let Some(from) = inherit.from() {
|
||||
let from = from.expr().unwrap().downgrade(ctx)?;
|
||||
let from = from.expr().unwrap().downgrade(ctx, mc)?;
|
||||
Some(ctx.new_thunk(from))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
for attr in inherit.attrs() {
|
||||
let ident = match downgrade_attr(attr, ctx)? {
|
||||
let ident = match downgrade_attr(attr, ctx, mc)? {
|
||||
Attr::Str(ident) => ident,
|
||||
_ => {
|
||||
return Err(Error::DowngradeError(
|
||||
@@ -709,7 +1007,11 @@ fn downgrade_inherit(
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn downgrade_attr(attr: ast::Attr, ctx: &mut DowngradeContext) -> Result<Attr> {
|
||||
fn downgrade_attr<'gc>(
|
||||
attr: ast::Attr,
|
||||
ctx: &mut DowngradeContext<'gc>,
|
||||
mc: &Mutation<'gc>,
|
||||
) -> Result<Attr> {
|
||||
use ast::Attr::*;
|
||||
use ast::InterpolPart::*;
|
||||
match attr {
|
||||
@@ -722,7 +1024,7 @@ fn downgrade_attr(attr: ast::Attr, ctx: &mut DowngradeContext) -> Result<Attr> {
|
||||
match parts.into_iter().next().unwrap() {
|
||||
Literal(ident) => Ok(Attr::Str(ctx.new_sym(ident))),
|
||||
Interpolation(interpol) => {
|
||||
Ok(Attr::Dynamic(interpol.expr().unwrap().downgrade(ctx)?))
|
||||
Ok(Attr::Dynamic(interpol.expr().unwrap().downgrade(ctx, mc)?))
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -730,30 +1032,35 @@ fn downgrade_attr(attr: ast::Attr, ctx: &mut DowngradeContext) -> Result<Attr> {
|
||||
.into_iter()
|
||||
.map(|part| match part {
|
||||
Literal(lit) => ctx.new_const(lit.into()).ir().ok(),
|
||||
Interpolation(interpol) => interpol.expr().unwrap().downgrade(ctx),
|
||||
Interpolation(interpol) => interpol.expr().unwrap().downgrade(ctx, mc),
|
||||
})
|
||||
.collect::<Result<Vec<_>>>()?;
|
||||
Ok(Attr::Strs(ConcatStrings { parts }))
|
||||
}
|
||||
}
|
||||
Dynamic(dynamic) => Ok(Attr::Dynamic(dynamic.expr().unwrap().downgrade(ctx)?)),
|
||||
Dynamic(dynamic) => Ok(Attr::Dynamic(dynamic.expr().unwrap().downgrade(ctx, mc)?)),
|
||||
}
|
||||
}
|
||||
|
||||
fn downgrade_attrpath(attrpath: ast::Attrpath, ctx: &mut DowngradeContext) -> Result<Vec<Attr>> {
|
||||
fn downgrade_attrpath<'gc>(
|
||||
attrpath: ast::Attrpath,
|
||||
ctx: &mut DowngradeContext<'gc>,
|
||||
mc: &Mutation<'gc>,
|
||||
) -> Result<Vec<Attr>> {
|
||||
attrpath
|
||||
.attrs()
|
||||
.map(|attr| downgrade_attr(attr, ctx))
|
||||
.map(|attr| downgrade_attr(attr, ctx, mc))
|
||||
.collect::<Result<Vec<_>>>()
|
||||
}
|
||||
|
||||
fn downgrade_attrpathvalue(
|
||||
fn downgrade_attrpathvalue<'gc>(
|
||||
value: ast::AttrpathValue,
|
||||
attrs: &mut Attrs,
|
||||
ctx: &mut DowngradeContext,
|
||||
ctx: &mut DowngradeContext<'gc>,
|
||||
mc: &Mutation<'gc>,
|
||||
) -> Result<()> {
|
||||
let path = downgrade_attrpath(value.attrpath().unwrap(), ctx)?;
|
||||
let value = value.value().unwrap().downgrade(ctx)?;
|
||||
let path = downgrade_attrpath(value.attrpath().unwrap(), ctx, mc)?;
|
||||
let value = value.value().unwrap().downgrade(ctx, mc)?;
|
||||
let value = match value {
|
||||
x @ Ir::Const(_) => x,
|
||||
x => ctx.new_thunk(x).ir(),
|
||||
|
||||
@@ -350,7 +350,7 @@ extern "C" fn helper_call<'gc>(
|
||||
|
||||
extern "C" fn helper_lookup(sym: usize, env: *const VmEnv) -> JITValue {
|
||||
let env = unsafe { env.as_ref() }.unwrap();
|
||||
let val: JITValue = env.lookup(&sym).unwrap().into();
|
||||
let val: JITValue = env.lookup_slow(&sym).unwrap().into();
|
||||
val
|
||||
}
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ use inkwell::context::Context;
|
||||
use ecow::EcoString;
|
||||
use rpds::vector_sync;
|
||||
|
||||
use crate::builtins::env;
|
||||
use crate::builtins::vm_env;
|
||||
use crate::compile::compile;
|
||||
use crate::ir::downgrade;
|
||||
use crate::jit::JITContext;
|
||||
|
||||
@@ -16,7 +16,7 @@ macro_rules! into {
|
||||
}
|
||||
|
||||
pub struct Stack<T, const CAP: usize> {
|
||||
items: [MaybeUninit<T>; CAP],
|
||||
items: Box<[MaybeUninit<T>; CAP]>,
|
||||
top: usize,
|
||||
}
|
||||
|
||||
@@ -37,7 +37,11 @@ impl<T, const CAP: usize> Default for Stack<T, CAP> {
|
||||
impl<T, const CAP: usize> Stack<T, CAP> {
|
||||
pub fn new() -> Self {
|
||||
Stack {
|
||||
items: [const { MaybeUninit::uninit() }; CAP],
|
||||
items: unsafe {
|
||||
std::mem::transmute::<Box<MaybeUninit<[T; CAP]>>, Box<[MaybeUninit<T>; CAP]>>(
|
||||
Box::new_uninit(),
|
||||
)
|
||||
},
|
||||
top: 0,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -608,7 +608,7 @@ impl<'gc> Thunk<'gc> {
|
||||
let _Thunk::Code(opcodes, env) =
|
||||
std::mem::replace(&mut *self.thunk.borrow_mut(mc), _Thunk::Suspended)
|
||||
else {
|
||||
return Err(Error::EvalError("infinite recursion occured".into()));
|
||||
return Err(Error::EvalError("infinite recursion encountered".into()));
|
||||
};
|
||||
Ok((opcodes, env.unwrap()))
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ use hashbrown::{HashMap, HashSet};
|
||||
use inkwell::context::Context;
|
||||
use itertools::Itertools;
|
||||
|
||||
use crate::builtins::env;
|
||||
use crate::builtins::vm_env;
|
||||
use crate::bytecode::{BinOp, Func as F, OpCode, OpCodes, Program, UnOp};
|
||||
use crate::env::VmEnv;
|
||||
use crate::error::*;
|
||||
@@ -22,7 +22,6 @@ use ecow::EcoString;
|
||||
mod test;
|
||||
|
||||
const STACK_SIZE: usize = 8 * 1024 / size_of::<Value>();
|
||||
type GcArena = Arena<Rootable!['gc => GcRoot<'gc>]>;
|
||||
|
||||
#[derive(Collect)]
|
||||
#[collect(require_static)]
|
||||
@@ -53,7 +52,7 @@ pub fn run(mut prog: Program) -> Result<p::Value> {
|
||||
vm,
|
||||
jit,
|
||||
stack: Stack::new(),
|
||||
envs: vec![env(&vm, mc)],
|
||||
envs: vec![vm_env(&vm, mc)],
|
||||
}
|
||||
});
|
||||
prog.top_level.reverse();
|
||||
@@ -331,7 +330,7 @@ fn single_op<'gc, const CAP: usize>(
|
||||
}
|
||||
OpCode::LookUp { sym } => {
|
||||
stack.push(
|
||||
env.lookup(&sym)
|
||||
env.lookup_slow(&sym)
|
||||
.ok_or_else(|| Error::EvalError(format!("{} not found", vm.get_sym(sym))))?
|
||||
.clone(),
|
||||
)?;
|
||||
|
||||
Reference in New Issue
Block a user