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