feat: a lot
This commit is contained in:
@@ -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!()
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user