feat: less clone, avoid evaluating not depended thunk

This commit is contained in:
2025-06-18 09:32:00 +08:00
parent 3e9f0a72a0
commit d875951c09
14 changed files with 409 additions and 192 deletions

View File

@@ -1,30 +1,30 @@
use ecow::EcoVec;
use crate::engine::Engine;
use crate::env::VmEnv;
use crate::env::Env;
use crate::error::{Error, Result};
use crate::ir::{self, DynAttr};
use crate::ty::common::Const;
use crate::ty::internal::{AttrSet, EnvRef, List, ThunkRef, Value};
use crate::ty::internal::{AttrSet, List, Value};
use crate::ty::public::Symbol;
pub mod jit;
pub trait Evaluate {
fn eval(self, engine: &mut Engine, env: &mut VmEnv) -> Result<Value>;
fn eval(&self, engine: &mut Engine, env: &mut Env) -> Result<Value>;
}
impl Evaluate for ir::Attrs {
fn eval(self, engine: &mut Engine, env: &mut VmEnv) -> Result<Value> {
fn eval(&self, engine: &mut Engine, env: &mut Env) -> Result<Value> {
let mut attrs = AttrSet::new(
self.stcs
.into_iter()
.map(|(k, v)| Ok((k, v.eval(engine, env)?)))
.iter()
.map(|(k, v)| Ok((k.clone(), v.eval(engine, env)?)))
.collect::<Result<_>>()?,
);
for DynAttr(k, v) in self.dyns {
for DynAttr(k, v) in self.dyns.iter() {
let mut k = k.eval(engine, env)?;
k.force(engine, env)?.coerce_to_string();
k.coerce_to_string();
attrs.push_attr(k.unwrap_string(), v.eval(engine, env)?);
}
Value::AttrSet(attrs.into()).ok()
@@ -32,10 +32,10 @@ impl Evaluate for ir::Attrs {
}
impl Evaluate for ir::List {
fn eval(self, engine: &mut Engine, env: &mut VmEnv) -> Result<Value> {
fn eval(&self, engine: &mut Engine, env: &mut Env) -> Result<Value> {
Value::List(List::from(
self.items
.into_iter()
.iter()
.map(|val| val.eval(engine, env))
.collect::<Result<EcoVec<_>>>()?,
))
@@ -44,16 +44,16 @@ impl Evaluate for ir::List {
}
impl Evaluate for ir::HasAttr {
fn eval(self, engine: &mut Engine, env: &mut VmEnv) -> Result<Value> {
fn eval(&self, engine: &mut Engine, env: &mut Env) -> Result<Value> {
use ir::Attr::*;
let mut val = self.lhs.eval(engine, env)?;
val.has_attr(self.rhs.into_iter().map(|attr| {
val.has_attr(self.rhs.iter().map(|attr| {
Ok(match attr {
Str(ident) => ident,
Str(ident) => ident.clone(),
Strs(expr) => expr.eval(engine, env)?.unwrap_string(),
Dynamic(expr) => {
let mut val = expr.eval(engine, env)?;
val.force(engine, env)?.coerce_to_string();
val.coerce_to_string();
val.unwrap_string()
}
})
@@ -63,12 +63,10 @@ impl Evaluate for ir::HasAttr {
}
impl Evaluate for ir::BinOp {
fn eval(self, engine: &mut Engine, env: &mut VmEnv) -> Result<Value> {
fn eval(&self, engine: &mut Engine, env: &mut Env) -> Result<Value> {
use ir::BinOpKind::*;
let mut lhs = self.lhs.eval(engine, env)?;
let mut rhs = self.rhs.eval(engine, env)?;
lhs.force(engine, env)?;
rhs.force(engine, env)?;
match self.kind {
Add => lhs.add(rhs),
Sub => {
@@ -115,10 +113,9 @@ impl Evaluate for ir::BinOp {
}
impl Evaluate for ir::UnOp {
fn eval(self, engine: &mut Engine, env: &mut VmEnv) -> Result<Value> {
fn eval(&self, engine: &mut Engine, env: &mut Env) -> Result<Value> {
use ir::UnOpKind::*;
let mut rhs = self.rhs.eval(engine, env)?;
rhs.force(engine, env)?;
match self.kind {
Neg => rhs.neg(),
Not => rhs.not(),
@@ -128,19 +125,19 @@ impl Evaluate for ir::UnOp {
}
impl Evaluate for ir::Select {
fn eval(self, engine: &mut Engine, env: &mut VmEnv) -> Result<Value> {
fn eval(&self, engine: &mut Engine, env: &mut Env) -> Result<Value> {
use ir::Attr::*;
let mut val = self.expr.eval(engine, env)?;
if let Some(default) = self.default {
if let Some(default) = &self.default {
let default = default.eval(engine, env)?;
val.force(engine, env)?.select_with_default(
self.attrpath.into_iter().map(|attr| {
val.select_with_default(
self.attrpath.iter().map(|attr| {
Ok(match attr {
Str(ident) => ident,
Str(ident) => ident.clone(),
Strs(expr) => expr.eval(engine, env)?.unwrap_string(),
Dynamic(expr) => {
let mut val = expr.eval(engine, env)?;
val.force(engine, env)?.coerce_to_string();
val.coerce_to_string();
val.unwrap_string()
}
})
@@ -148,14 +145,14 @@ impl Evaluate for ir::Select {
default,
)?;
} else {
val.force(engine, env)?
.select(self.attrpath.into_iter().map(|attr| {
val
.select(self.attrpath.iter().map(|attr| {
Ok(match attr {
Str(ident) => ident,
Str(ident) => ident.clone(),
Strs(expr) => expr.eval(engine, env)?.unwrap_string(),
Dynamic(expr) => {
let mut val = expr.eval(engine, env)?;
val.force(engine, env)?.coerce_to_string();
val.coerce_to_string();
val.unwrap_string()
}
})
@@ -166,7 +163,7 @@ impl Evaluate for ir::Select {
}
impl Evaluate for ir::If {
fn eval(self, engine: &mut Engine, env: &mut VmEnv) -> Result<Value> {
fn eval(&self, engine: &mut Engine, env: &mut Env) -> Result<Value> {
// TODO: Error Handling
let cond = self.cond.eval(engine, env)?.unwrap_bool();
if cond {
@@ -178,19 +175,18 @@ impl Evaluate for ir::If {
}
impl Evaluate for ir::LoadFunc {
fn eval(self, engine: &mut Engine, env: &mut VmEnv) -> Result<Value> {
fn eval(&self, engine: &mut Engine, env: &mut Env) -> Result<Value> {
let idx = engine.func_offset + self.idx;
Value::Func(idx).ok()
}
}
impl Evaluate for ir::Call {
fn eval(self, engine: &mut Engine, env: &mut VmEnv) -> Result<Value> {
fn eval(&self, engine: &mut Engine, env: &mut Env) -> Result<Value> {
let mut func = self.func.eval(engine, env)?;
func.force(engine, env)?;
func.call(
self.args
.into_iter()
.iter()
.map(|arg| arg.eval(engine, env))
.collect::<Result<_>>()?,
engine,
@@ -205,13 +201,13 @@ impl Evaluate for ir::Call {
}
impl Evaluate for ir::Let {
fn eval(self, engine: &mut Engine, env: &mut VmEnv) -> Result<Value> {
fn eval(&self, engine: &mut Engine, env: &mut Env) -> Result<Value> {
unreachable!()
}
}
impl Evaluate for ir::With {
fn eval(self, engine: &mut Engine, env: &mut VmEnv) -> Result<Value> {
fn eval(&self, engine: &mut Engine, env: &mut Env) -> Result<Value> {
let namespace = self.namespace.eval(engine, env)?;
// TODO: Error Handling
env.enter_with(namespace.unwrap_attr_set().into_inner());
@@ -222,19 +218,19 @@ impl Evaluate for ir::With {
}
impl Evaluate for ir::Assert {
fn eval(self, engine: &mut Engine, env: &mut VmEnv) -> Result<Value> {
fn eval(&self, engine: &mut Engine, env: &mut Env) -> Result<Value> {
todo!()
}
}
impl Evaluate for ir::ConcatStrings {
fn eval(self, engine: &mut Engine, env: &mut VmEnv) -> Result<Value> {
fn eval(&self, engine: &mut Engine, env: &mut Env) -> Result<Value> {
let mut parts = self
.parts
.into_iter()
.iter()
.map(|part| {
let mut part = part.eval(engine, env)?;
part.force(engine, env)?.coerce_to_string();
part.coerce_to_string();
part.ok()
})
.collect::<Result<Vec<_>>>()?
@@ -250,13 +246,13 @@ impl Evaluate for ir::ConcatStrings {
}
impl Evaluate for ir::String {
fn eval(self, _: &mut Engine, _: &mut VmEnv) -> Result<Value> {
Value::String(self.val).ok()
fn eval(&self, _: &mut Engine, _: &mut Env) -> Result<Value> {
Value::String(self.val.clone()).ok()
}
}
impl Evaluate for ir::Const {
fn eval(self, _: &mut Engine, _: &mut VmEnv) -> Result<Value> {
fn eval(&self, _: &mut Engine, _: &mut Env) -> Result<Value> {
match self.val {
Const::Null => Value::Null,
Const::Int(x) => Value::Int(x),
@@ -268,33 +264,34 @@ impl Evaluate for ir::Const {
}
impl Evaluate for ir::Var {
fn eval(self, _: &mut Engine, env: &mut VmEnv) -> Result<Value> {
fn eval(&self, _: &mut Engine, env: &mut Env) -> Result<Value> {
env.lookup_with(&self.sym).ok_or_else(|| {
Error::EvalError(format!("variable {} not found", Symbol::from(self.sym)))
Error::EvalError(format!("variable {} not found", Symbol::from(self.sym.clone())))
})
}
}
impl Evaluate for ir::Arg {
fn eval(self, _: &mut Engine, env: &mut VmEnv) -> Result<Value> {
fn eval(&self, _: &mut Engine, env: &mut Env) -> Result<Value> {
env.lookup_arg(self.level).clone().ok()
}
}
impl Evaluate for ir::LetVar {
fn eval(self, _: &mut Engine, env: &mut VmEnv) -> Result<Value> {
fn eval(&self, _: &mut Engine, env: &mut Env) -> Result<Value> {
unreachable!()
}
}
impl Evaluate for ir::Thunk {
fn eval(self, _: &mut Engine, _: &mut VmEnv) -> Result<Value> {
Value::Thunk(ThunkRef::new(self.idx)).ok()
fn eval(&self, engine: &mut Engine, env: &mut Env) -> Result<Value> {
env.lookup_cache(self.idx, |env| engine.eval_thunk(self.idx, env))
// Value::Thunk(self.idx).ok()
}
}
impl Evaluate for ir::MaybeThunk {
fn eval(self, engine: &mut Engine, env: &mut VmEnv) -> Result<Value> {
fn eval(&self, engine: &mut Engine, env: &mut Env) -> Result<Value> {
match self {
ir::MaybeThunk::Const(cnst) => cnst.eval(engine, env),
ir::MaybeThunk::String(string) => string.eval(engine, env),
@@ -304,7 +301,7 @@ impl Evaluate for ir::MaybeThunk {
}
impl Evaluate for ir::Path {
fn eval(self, engine: &mut Engine, env: &mut VmEnv) -> Result<Value> {
fn eval(&self, engine: &mut Engine, env: &mut Env) -> Result<Value> {
todo!()
}
}