feat: a lot

This commit is contained in:
2025-08-06 18:30:19 +08:00
parent 32c602f21c
commit f946cb2fd1
22 changed files with 735 additions and 591 deletions

View File

@@ -3,7 +3,7 @@ use std::rc::Rc;
use hashbrown::HashMap;
use nixjit_error::{Error, Result};
use nixjit_ir::{self as ir, ExprId};
use nixjit_ir::{self as ir, ArgIdx, ExprId, PrimOpId};
use nixjit_lir as lir;
use nixjit_value::{Const, Symbol};
@@ -12,35 +12,31 @@ pub use crate::value::*;
mod value;
pub trait EvalContext: Sized {
fn eval(&mut self, expr: ExprId) -> Result<Value<Self>>;
fn eval(&mut self, expr: &ExprId) -> Result<Value>;
fn with_with_env<T>(
&mut self,
namespace: Rc<HashMap<String, Value<Self>>>,
namespace: Rc<HashMap<String, Value>>,
f: impl FnOnce(&mut Self) -> T,
) -> T;
fn with_args_env<T>(
&mut self,
args: Vec<Value<Self>>,
f: impl FnOnce(&mut Self) -> T,
) -> (Vec<Value<Self>>, T);
fn lookup_with<'a>(&'a self, ident: &str) -> Option<&'a Value<Self>>;
fn lookup_arg<'a>(&'a self, offset: usize) -> Option<&'a Value<Self>>;
fn pop_frame(&mut self) -> Vec<Value<Self>>;
fn consume_arg(&mut self, func: ExprId) -> Result<bool>;
fn with_args_env<T>(&mut self, args: Vec<Value>, f: impl FnOnce(&mut Self) -> T) -> (Vec<Value>, T);
fn lookup_with<'a>(&'a self, ident: &str) -> Option<&'a Value>;
fn lookup_arg<'a>(&'a self, idx: ArgIdx) -> &'a Value;
fn pop_frame(&mut self) -> Vec<Value>;
fn call_primop(&mut self, id: PrimOpId, args: Vec<Value>) -> Result<Value>;
}
pub trait Evaluate<Ctx: EvalContext> {
fn eval(&self, ctx: &mut Ctx) -> Result<Value<Ctx>>;
fn eval(&self, ctx: &mut Ctx) -> Result<Value>;
}
impl<Ctx: EvalContext> Evaluate<Ctx> for ExprId {
fn eval(&self, ctx: &mut Ctx) -> Result<Value<Ctx>> {
ctx.eval(*self)
fn eval(&self, ctx: &mut Ctx) -> Result<Value> {
ctx.eval(self)
}
}
impl<Ctx: EvalContext> Evaluate<Ctx> for lir::Lir {
fn eval(&self, ctx: &mut Ctx) -> Result<Value<Ctx>> {
fn eval(&self, ctx: &mut Ctx) -> Result<Value> {
use lir::Lir::*;
match self {
AttrSet(x) => x.eval(ctx),
@@ -58,26 +54,16 @@ impl<Ctx: EvalContext> Evaluate<Ctx> for lir::Lir {
Str(x) => x.eval(ctx),
Var(x) => x.eval(ctx),
Path(x) => x.eval(ctx),
ExprRef(expr) => expr.eval(ctx),
&FuncRef(func) => {
if ctx.consume_arg(func)? {
ctx.eval(func)
} else {
Ok(Value::Func(func))
}
},
&ArgRef(arg) => {
let idx: usize = unsafe { core::mem::transmute(arg) };
ctx.lookup_arg(idx)
.cloned()
.ok_or_else(|| Error::EvalError("argument not found".to_string()))
}
ExprRef(expr) => ctx.eval(expr),
FuncRef(func) => Ok(Value::Func(unsafe { func.clone() })),
&ArgRef(idx) => Ok(ctx.lookup_arg(idx).clone()),
&PrimOp(primop) => Ok(Value::PrimOp(primop)),
}
}
}
impl<Ctx: EvalContext> Evaluate<Ctx> for ir::AttrSet {
fn eval(&self, ctx: &mut Ctx) -> Result<Value<Ctx>> {
fn eval(&self, ctx: &mut Ctx) -> Result<Value> {
let mut attrs = AttrSet::new(
self.stcs
.iter()
@@ -99,7 +85,7 @@ impl<Ctx: EvalContext> Evaluate<Ctx> for ir::AttrSet {
}
impl<Ctx: EvalContext> Evaluate<Ctx> for ir::List {
fn eval(&self, ctx: &mut Ctx) -> Result<Value<Ctx>> {
fn eval(&self, ctx: &mut Ctx) -> Result<Value> {
let items = self
.items
.iter()
@@ -111,7 +97,7 @@ impl<Ctx: EvalContext> Evaluate<Ctx> for ir::List {
}
impl<Ctx: EvalContext> Evaluate<Ctx> for ir::HasAttr {
fn eval(&self, ctx: &mut Ctx) -> Result<Value<Ctx>> {
fn eval(&self, ctx: &mut Ctx) -> Result<Value> {
use ir::Attr::*;
let mut val = self.lhs.eval(ctx)?;
val.has_attr(self.rhs.iter().map(|attr| {
@@ -130,7 +116,7 @@ impl<Ctx: EvalContext> Evaluate<Ctx> for ir::HasAttr {
}
impl<Ctx: EvalContext> Evaluate<Ctx> for ir::BinOp {
fn eval(&self, ctx: &mut Ctx) -> Result<Value<Ctx>> {
fn eval(&self, ctx: &mut Ctx) -> Result<Value> {
use ir::BinOpKind::*;
let mut lhs = self.lhs.eval(ctx)?;
let mut rhs = self.rhs.eval(ctx)?;
@@ -169,9 +155,9 @@ impl<Ctx: EvalContext> Evaluate<Ctx> for ir::BinOp {
}
Con => lhs.concat(rhs),
Upd => lhs.update(rhs),
PipeL => lhs.call(vec![rhs], ctx)?,
PipeL => lhs.call(core::iter::once(Ok(rhs)), ctx)?,
PipeR => {
rhs.call(vec![lhs], ctx)?;
rhs.call(core::iter::once(Ok(lhs)), ctx)?;
lhs = rhs;
}
}
@@ -180,7 +166,7 @@ impl<Ctx: EvalContext> Evaluate<Ctx> for ir::BinOp {
}
impl<Ctx: EvalContext> Evaluate<Ctx> for ir::UnOp {
fn eval(&self, ctx: &mut Ctx) -> Result<Value<Ctx>> {
fn eval(&self, ctx: &mut Ctx) -> Result<Value> {
use ir::UnOpKind::*;
let mut rhs = self.rhs.eval(ctx)?;
match self.kind {
@@ -196,7 +182,7 @@ impl<Ctx: EvalContext> Evaluate<Ctx> for ir::UnOp {
}
impl<Ctx: EvalContext> Evaluate<Ctx> for ir::Select {
fn eval(&self, ctx: &mut Ctx) -> Result<Value<Ctx>> {
fn eval(&self, ctx: &mut Ctx) -> Result<Value> {
use ir::Attr::*;
let mut val = self.expr.eval(ctx)?;
if let Some(default) = &self.default {
@@ -232,7 +218,7 @@ impl<Ctx: EvalContext> Evaluate<Ctx> for ir::Select {
}
impl<Ctx: EvalContext> Evaluate<Ctx> for ir::If {
fn eval(&self, ctx: &mut Ctx) -> Result<Value<Ctx>> {
fn eval(&self, ctx: &mut Ctx) -> Result<Value> {
// TODO: Error Handling
let cond = self.cond.eval(ctx)?;
let cond = cond
@@ -248,21 +234,22 @@ impl<Ctx: EvalContext> Evaluate<Ctx> for ir::If {
}
impl<Ctx: EvalContext> Evaluate<Ctx> for ir::Call {
fn eval(&self, ctx: &mut Ctx) -> Result<Value<Ctx>> {
fn eval(&self, ctx: &mut Ctx) -> Result<Value> {
let mut func = self.func.eval(ctx)?;
// FIXME: ?
let ctx_mut = unsafe { &mut *(ctx as *mut Ctx) };
func.call(
self.args
.iter()
.map(|arg| arg.eval(ctx))
.collect::<Result<_>>()?,
ctx,
.map(|arg| arg.eval(ctx)),
ctx_mut,
)?;
Ok(func.ok().unwrap())
}
}
impl<Ctx: EvalContext> Evaluate<Ctx> for ir::With {
fn eval(&self, ctx: &mut Ctx) -> Result<Value<Ctx>> {
fn eval(&self, ctx: &mut Ctx) -> Result<Value> {
let namespace = self.namespace.eval(ctx)?;
ctx.with_with_env(
namespace
@@ -275,7 +262,7 @@ impl<Ctx: EvalContext> Evaluate<Ctx> for ir::With {
}
impl<Ctx: EvalContext> Evaluate<Ctx> for ir::Assert {
fn eval(&self, ctx: &mut Ctx) -> Result<Value<Ctx>> {
fn eval(&self, ctx: &mut Ctx) -> Result<Value> {
let cond = self.assertion.eval(ctx)?;
let cond = cond
.try_unwrap_bool()
@@ -289,7 +276,7 @@ impl<Ctx: EvalContext> Evaluate<Ctx> for ir::Assert {
}
impl<Ctx: EvalContext> Evaluate<Ctx> for ir::ConcatStrings {
fn eval(&self, ctx: &mut Ctx) -> Result<Value<Ctx>> {
fn eval(&self, ctx: &mut Ctx) -> Result<Value> {
let mut parts = self
.parts
.iter()
@@ -310,14 +297,14 @@ impl<Ctx: EvalContext> Evaluate<Ctx> for ir::ConcatStrings {
}
impl<Ctx: EvalContext> Evaluate<Ctx> for ir::Str {
fn eval(&self, _: &mut Ctx) -> Result<Value<Ctx>> {
fn eval(&self, _: &mut Ctx) -> Result<Value> {
let result = Value::String(self.val.clone()).ok();
Ok(result.unwrap())
}
}
impl<Ctx: EvalContext> Evaluate<Ctx> for ir::Const {
fn eval(&self, _: &mut Ctx) -> Result<Value<Ctx>> {
fn eval(&self, _: &mut Ctx) -> Result<Value> {
let result = match self.val {
Const::Null => Value::Null,
Const::Int(x) => Value::Int(x),
@@ -330,7 +317,7 @@ impl<Ctx: EvalContext> Evaluate<Ctx> for ir::Const {
}
impl<Ctx: EvalContext> Evaluate<Ctx> for ir::Var {
fn eval(&self, ctx: &mut Ctx) -> Result<Value<Ctx>> {
fn eval(&self, ctx: &mut Ctx) -> Result<Value> {
ctx.lookup_with(&self.sym)
.ok_or_else(|| {
Error::EvalError(format!(
@@ -343,7 +330,7 @@ impl<Ctx: EvalContext> Evaluate<Ctx> for ir::Var {
}
impl<Ctx: EvalContext> Evaluate<Ctx> for ir::Path {
fn eval(&self, ctx: &mut Ctx) -> Result<Value<Ctx>> {
fn eval(&self, ctx: &mut Ctx) -> Result<Value> {
todo!()
}
}