fix: WIP
This commit is contained in:
30
Cargo.lock
generated
30
Cargo.lock
generated
@@ -291,6 +291,12 @@ version = "0.3.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2acce4a10f12dc2fb14a218589d4f1f62ef011b2d0cc4b3cb1bba8e94da14649"
|
checksum = "2acce4a10f12dc2fb14a218589d4f1f62ef011b2d0cc4b3cb1bba8e94da14649"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "fixedbitset"
|
||||||
|
version = "0.5.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1d674e81391d1e1ab681a28d99df07927c6d4aa5b027d7da16ba32d1d21ecd99"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "foldhash"
|
name = "foldhash"
|
||||||
version = "0.1.5"
|
version = "0.1.5"
|
||||||
@@ -389,6 +395,17 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "nixjit"
|
name = "nixjit"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"hashbrown 0.15.4",
|
||||||
|
"nixjit_context",
|
||||||
|
"nixjit_error",
|
||||||
|
"nixjit_eval",
|
||||||
|
"nixjit_hir",
|
||||||
|
"nixjit_ir",
|
||||||
|
"nixjit_lir",
|
||||||
|
"nixjit_value",
|
||||||
|
"rnix",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "nixjit_context"
|
name = "nixjit_context"
|
||||||
@@ -407,6 +424,7 @@ dependencies = [
|
|||||||
"nixjit_jit",
|
"nixjit_jit",
|
||||||
"nixjit_lir",
|
"nixjit_lir",
|
||||||
"nixjit_value",
|
"nixjit_value",
|
||||||
|
"petgraph",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -505,6 +523,18 @@ dependencies = [
|
|||||||
"regex",
|
"regex",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "petgraph"
|
||||||
|
version = "0.8.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "54acf3a685220b533e437e264e4d932cfbdc4cc7ec0cd232ed73c08d03b8a7ca"
|
||||||
|
dependencies = [
|
||||||
|
"fixedbitset",
|
||||||
|
"hashbrown 0.15.4",
|
||||||
|
"indexmap",
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "proc-macro2"
|
name = "proc-macro2"
|
||||||
version = "1.0.95"
|
version = "1.0.95"
|
||||||
|
|||||||
@@ -4,3 +4,13 @@ version = "0.1.0"
|
|||||||
edition = "2024"
|
edition = "2024"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
rnix = "0.12"
|
||||||
|
hashbrown = "0.15"
|
||||||
|
|
||||||
|
nixjit_context = { path = "../nixjit_context" }
|
||||||
|
nixjit_error = { path = "../nixjit_error" }
|
||||||
|
nixjit_eval = { path = "../nixjit_eval" }
|
||||||
|
nixjit_hir = { path = "../nixjit_hir" }
|
||||||
|
nixjit_ir = { path = "../nixjit_ir" }
|
||||||
|
nixjit_lir = { path = "../nixjit_lir" }
|
||||||
|
nixjit_value = { path = "../nixjit_value" }
|
||||||
|
|||||||
@@ -1,14 +1,3 @@
|
|||||||
pub fn add(left: u64, right: u64) -> u64 {
|
|
||||||
left + right
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod test;
|
||||||
use super::*;
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn it_works() {
|
|
||||||
let result = add(2, 2);
|
|
||||||
assert_eq!(result, 4);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -3,18 +3,20 @@
|
|||||||
|
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
|
|
||||||
use crate::ir::downgrade;
|
use hashbrown::HashSet;
|
||||||
use crate::ty::common::Const;
|
use nixjit_context::Context;
|
||||||
use crate::ty::public::*;
|
use nixjit_eval::EvalContext;
|
||||||
|
use nixjit_hir::Downgrade;
|
||||||
use super::eval;
|
use nixjit_lir::ResolveContext;
|
||||||
|
use nixjit_value::{AttrSet, Const, List, Symbol, Value};
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn test_expr(expr: &str, expected: Value) {
|
fn test_expr(expr: &str, expected: Value) {
|
||||||
println!("{expr}");
|
println!("{expr}");
|
||||||
let downgraded = downgrade(rnix::Root::parse(expr).tree().expr().unwrap()).unwrap();
|
let mut ctx = Context::new();
|
||||||
println!("{downgraded:#?}");
|
let expr = rnix::Root::parse(expr).tree().expr().unwrap().downgrade(&mut ctx).unwrap();
|
||||||
assert_eq!(eval(downgraded).unwrap(), expected);
|
ctx.resolve(expr).unwrap();
|
||||||
|
assert_eq!(ctx.eval(expr).unwrap().to_public(&ctx, &mut HashSet::new()), expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! map {
|
macro_rules! map {
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ edition = "2024"
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
hashbrown = "0.15"
|
hashbrown = "0.15"
|
||||||
itertools = "0.14"
|
itertools = "0.14"
|
||||||
|
petgraph = "0.8"
|
||||||
|
|
||||||
cranelift = "0.122"
|
cranelift = "0.122"
|
||||||
cranelift-module = "0.122"
|
cranelift-module = "0.122"
|
||||||
|
|||||||
@@ -1,30 +1,50 @@
|
|||||||
use core::mem::MaybeUninit;
|
use core::mem::MaybeUninit;
|
||||||
use std::cell::{OnceCell, RefCell};
|
use std::cell::{OnceCell, RefCell};
|
||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
use hashbrown::{HashMap, HashSet};
|
use hashbrown::{HashMap, HashSet};
|
||||||
use itertools::Itertools;
|
use petgraph::algo::toposort;
|
||||||
|
use petgraph::graph::{DiGraph, NodeIndex};
|
||||||
|
|
||||||
use nixjit_error::Result;
|
use nixjit_error::{Error, Result};
|
||||||
use nixjit_eval::EvalContext;
|
use nixjit_eval::{EvalContext, Evaluate, Value};
|
||||||
use nixjit_hir::{DowngradeContext, Hir};
|
use nixjit_hir::{DowngradeContext, Hir};
|
||||||
use nixjit_ir::{ExprId, Param};
|
use nixjit_ir::{ArgIdx, ExprId, Param};
|
||||||
use nixjit_lir::{Lir, ResolveContext};
|
use nixjit_lir::{Lir, LookupResult, Resolve, ResolveContext};
|
||||||
use nixjit_value::Value;
|
|
||||||
|
|
||||||
use nixjit_jit::{JITCompiler, JITContext, JITFunc};
|
use nixjit_jit::{JITCompiler, JITContext, JITFunc};
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct Frame {
|
||||||
|
values: Vec<Value<Context>>,
|
||||||
|
left: usize,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct Context {
|
pub struct Context {
|
||||||
hirs: Vec<RefCell<Hir>>,
|
hirs: Vec<RefCell<Hir>>,
|
||||||
lirs: Vec<MaybeUninit<Lir>>,
|
lirs: Vec<MaybeUninit<Lir>>,
|
||||||
|
resolved: Vec<bool>,
|
||||||
|
scopes: Vec<HashMap<String, LookupResult>>,
|
||||||
|
funcs: HashMap<ExprId, Param>,
|
||||||
|
graph: DiGraph<ExprId, ()>,
|
||||||
|
nodes: Vec<NodeIndex>,
|
||||||
|
|
||||||
|
stack: Vec<Frame>,
|
||||||
|
with_scopes: Vec<Rc<HashMap<String, Value<Self>>>>,
|
||||||
|
|
||||||
jit: JITCompiler<Self>,
|
jit: JITCompiler<Self>,
|
||||||
compiled: Vec<OnceCell<JITFunc<Self>>>,
|
compiled: Vec<OnceCell<JITFunc<Self>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Drop for Context {
|
impl Drop for Context {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
unsafe {
|
for (i, lir) in self.lirs.iter_mut().enumerate() {
|
||||||
self.lirs.iter_mut().for_each(|lir| lir.assume_init_drop());
|
if self.resolved[i] {
|
||||||
|
unsafe {
|
||||||
|
lir.assume_init_drop();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -37,20 +57,22 @@ impl Context {
|
|||||||
|
|
||||||
impl DowngradeContext for Context {
|
impl DowngradeContext for Context {
|
||||||
fn new_expr(&mut self, expr: Hir) -> ExprId {
|
fn new_expr(&mut self, expr: Hir) -> ExprId {
|
||||||
let id = unsafe { core::mem::transmute(self.hirs.len() + self.lirs.len()) };
|
let id = ExprId::from(self.hirs.len());
|
||||||
self.hirs.push(expr.into());
|
self.hirs.push(expr.into());
|
||||||
|
self.lirs.push(MaybeUninit::uninit());
|
||||||
|
self.nodes.push(self.graph.add_node(id));
|
||||||
|
self.resolved.push(false);
|
||||||
|
self.compiled.push(OnceCell::new());
|
||||||
id
|
id
|
||||||
}
|
}
|
||||||
fn with_expr<T>(&self, id: ExprId, f: impl FnOnce(&Hir, &Self) -> T) -> T {
|
fn with_expr<T>(&self, id: ExprId, f: impl FnOnce(&Hir, &Self) -> T) -> T {
|
||||||
unsafe {
|
let idx = usize::from(id);
|
||||||
let idx: usize = core::mem::transmute(id);
|
f(&self.hirs[idx].borrow(), self)
|
||||||
f(&self.hirs.get_unchecked(idx).borrow(), self)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
fn with_expr_mut<T>(&mut self, id: ExprId, f: impl FnOnce(&mut Hir, &mut Self) -> T) -> T {
|
fn with_expr_mut<T>(&mut self, id: ExprId, f: impl FnOnce(&mut Hir, &mut Self) -> T) -> T {
|
||||||
|
let idx = usize::from(id);
|
||||||
unsafe {
|
unsafe {
|
||||||
let self_mut = &mut *(self as *mut Context);
|
let self_mut = &mut *(self as *mut Self);
|
||||||
let idx: usize = core::mem::transmute(id);
|
|
||||||
f(&mut self.hirs.get_unchecked_mut(idx).borrow_mut(), self_mut)
|
f(&mut self.hirs.get_unchecked_mut(idx).borrow_mut(), self_mut)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -58,88 +80,163 @@ impl DowngradeContext for Context {
|
|||||||
|
|
||||||
impl ResolveContext for Context {
|
impl ResolveContext for Context {
|
||||||
fn lookup(&self, name: &str) -> nixjit_lir::LookupResult {
|
fn lookup(&self, name: &str) -> nixjit_lir::LookupResult {
|
||||||
todo!()
|
for scope in self.scopes.iter().rev() {
|
||||||
|
if let Some(val) = scope.get(name) {
|
||||||
|
return val.clone();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
LookupResult::NotFound
|
||||||
}
|
}
|
||||||
|
|
||||||
fn new_dep(&mut self, expr: ExprId, dep: ExprId) {
|
fn new_dep(&mut self, expr: ExprId, dep: ExprId) {
|
||||||
todo!()
|
let expr = *self.nodes.get(usize::from(expr)).unwrap();
|
||||||
|
let dep = *self.nodes.get(usize::from(dep)).unwrap();
|
||||||
|
self.graph.add_edge(expr, dep, ());
|
||||||
}
|
}
|
||||||
|
|
||||||
fn resolve(&mut self, expr: ExprId) -> Result<()> {
|
fn resolve(&mut self, expr: ExprId) -> Result<()> {
|
||||||
todo!()
|
let idx = usize::from(expr);
|
||||||
|
if self.resolved[idx] {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
let hir = self.hirs[idx].replace(nixjit_hir::Hir::Const(nixjit_ir::Const::from(false)));
|
||||||
|
let lir = hir.resolve(self)?;
|
||||||
|
self.lirs[idx].write(lir);
|
||||||
|
self.resolved[idx] = true;
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn new_func(&mut self, body: ExprId, param: Param) {
|
fn new_func(&mut self, body: ExprId, param: Param) {
|
||||||
todo!()
|
self.funcs.insert(body, param);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn with_let_env<'a, T>(
|
fn with_let_env<'a, T>(
|
||||||
&mut self,
|
&mut self,
|
||||||
bindings: impl IntoIterator<Item = (&'a String, &'a ExprId)>,
|
bindings: impl IntoIterator<Item = (&'a String, &'a ExprId)>,
|
||||||
f: impl FnOnce(&mut Self) -> T,
|
f: impl FnOnce(&mut Self) -> T,
|
||||||
) -> T {
|
) -> T {
|
||||||
todo!()
|
let mut scope = HashMap::new();
|
||||||
|
for (name, expr) in bindings {
|
||||||
|
scope.insert(name.clone(), LookupResult::Expr(*expr));
|
||||||
|
}
|
||||||
|
self.scopes.push(scope);
|
||||||
|
let res = f(self);
|
||||||
|
self.scopes.pop();
|
||||||
|
res
|
||||||
}
|
}
|
||||||
|
|
||||||
fn with_with_env<T>(&mut self, f: impl FnOnce(&mut Self) -> T) -> (bool, T) {
|
fn with_with_env<T>(&mut self, f: impl FnOnce(&mut Self) -> T) -> (bool, T) {
|
||||||
todo!()
|
self.scopes.push(HashMap::new());
|
||||||
|
let res = f(self);
|
||||||
|
self.scopes.pop();
|
||||||
|
(true, res)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn with_param_env<'a, T>(
|
fn with_param_env<'a, T>(
|
||||||
&mut self,
|
&mut self,
|
||||||
ident: Option<&'a str>,
|
ident: Option<&'a str>,
|
||||||
f: impl FnOnce(&mut Self) -> T,
|
f: impl FnOnce(&mut Self) -> T,
|
||||||
) -> T {
|
) -> T {
|
||||||
todo!()
|
let mut scope = HashMap::new();
|
||||||
|
if let Some(ident) = ident {
|
||||||
|
scope.insert(ident.to_string(), LookupResult::Arg(ArgIdx::from(0)));
|
||||||
|
}
|
||||||
|
self.scopes.push(scope);
|
||||||
|
let res = f(self);
|
||||||
|
self.scopes.pop();
|
||||||
|
res
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl EvalContext for Context {
|
impl EvalContext for Context {
|
||||||
fn eval(&mut self, expr: ExprId) -> Result<nixjit_eval::Value<Self>>
|
fn eval(&mut self, expr: ExprId) -> Result<nixjit_eval::Value<Self>> {
|
||||||
where
|
let idx = usize::from(expr);
|
||||||
Self: Sized,
|
let lir = unsafe { &*(self.lirs[idx].assume_init_ref() as *const Lir) };
|
||||||
{
|
lir.eval(self)
|
||||||
todo!()
|
|
||||||
}
|
}
|
||||||
fn pop_frame(&mut self) -> Vec<nixjit_eval::Value<Self>>
|
|
||||||
where
|
fn pop_frame(&mut self) -> Vec<nixjit_eval::Value<Self>> {
|
||||||
Self: Sized,
|
self.stack.pop().unwrap().values
|
||||||
{
|
|
||||||
todo!()
|
|
||||||
}
|
}
|
||||||
fn lookup_with<'a>(&'a self, ident: &str) -> Option<&'a nixjit_eval::Value<Self>>
|
|
||||||
where
|
fn lookup_with<'a>(&'a self, ident: &str) -> Option<&'a nixjit_eval::Value<Self>> {
|
||||||
Self: Sized,
|
for scope in self.with_scopes.iter().rev() {
|
||||||
{
|
if let Some(val) = scope.get(ident) {
|
||||||
todo!()
|
return Some(val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn lookup_arg<'a>(&'a self, offset: usize) -> Option<&'a Value<Self>> {
|
||||||
|
self.stack.last().and_then(|frame| frame.values.get(offset))
|
||||||
|
}
|
||||||
|
|
||||||
fn with_with_env<T>(
|
fn with_with_env<T>(
|
||||||
&mut self,
|
&mut self,
|
||||||
namespace: std::rc::Rc<HashMap<String, nixjit_eval::Value<Self>>>,
|
namespace: std::rc::Rc<HashMap<String, nixjit_eval::Value<Self>>>,
|
||||||
f: impl FnOnce(&mut Self) -> T,
|
f: impl FnOnce(&mut Self) -> T,
|
||||||
) -> T
|
) -> T {
|
||||||
where
|
self.with_scopes.push(namespace);
|
||||||
Self: Sized,
|
let res = f(self);
|
||||||
{
|
self.with_scopes.pop();
|
||||||
todo!()
|
res
|
||||||
}
|
}
|
||||||
|
|
||||||
fn with_args_env<T>(
|
fn with_args_env<T>(
|
||||||
&mut self,
|
&mut self,
|
||||||
args: Vec<nixjit_eval::Value<Self>>,
|
args: Vec<nixjit_eval::Value<Self>>,
|
||||||
f: impl FnOnce(&mut Self) -> T,
|
f: impl FnOnce(&mut Self) -> T,
|
||||||
) -> (Vec<nixjit_eval::Value<Self>>, T)
|
) -> (Vec<nixjit_eval::Value<Self>>, T) {
|
||||||
where
|
self.stack.push(Frame {
|
||||||
Self: Sized,
|
left: args.len(),
|
||||||
{
|
values: args,
|
||||||
todo!()
|
});
|
||||||
|
let res = f(self);
|
||||||
|
(self.stack.pop().unwrap().values, res)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn consume_arg(&mut self, func: ExprId) -> Result<bool> {
|
||||||
|
let Some(frame) = self.stack.last_mut() else {
|
||||||
|
return Ok(false);
|
||||||
|
};
|
||||||
|
if frame.left == 0 {
|
||||||
|
return Ok(false);
|
||||||
|
}
|
||||||
|
frame.left -= 1;
|
||||||
|
let param = self.funcs.get(&func).unwrap();
|
||||||
|
if let Some(required) = ¶m.required {
|
||||||
|
let attrs = frame.values[frame.values.len() - frame.left - 1]
|
||||||
|
.as_ref()
|
||||||
|
.try_unwrap_attr_set()
|
||||||
|
.map_err(|_| Error::EvalError(format!("expected a set but found ...")))?;
|
||||||
|
if required.iter().any(|attr| attrs.get(attr).is_none())
|
||||||
|
|| param.allowed.as_ref().map_or(false, |allowed| {
|
||||||
|
attrs.iter().any(|(attr, _)| allowed.get(attr).is_none())
|
||||||
|
})
|
||||||
|
{
|
||||||
|
return Err(Error::EvalError(format!("TODO")));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl JITContext for Context {
|
impl JITContext for Context {
|
||||||
fn lookup_arg(&self, offset: usize) -> &nixjit_eval::Value<Self> {
|
fn lookup_arg(&self, offset: usize) -> &nixjit_eval::Value<Self> {
|
||||||
todo!()
|
&self.stack.last().unwrap().values[offset]
|
||||||
}
|
}
|
||||||
|
|
||||||
fn lookup_stack(&self, offset: usize) -> &nixjit_eval::Value<Self> {
|
fn lookup_stack(&self, offset: usize) -> &nixjit_eval::Value<Self> {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn enter_with(&mut self, namespace: std::rc::Rc<HashMap<String, nixjit_eval::Value<Self>>>) {
|
fn enter_with(&mut self, namespace: std::rc::Rc<HashMap<String, nixjit_eval::Value<Self>>>) {
|
||||||
todo!()
|
self.with_scopes.push(namespace);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn exit_with(&mut self) {
|
fn exit_with(&mut self) {
|
||||||
todo!()
|
self.with_scopes.pop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,7 +24,9 @@ pub trait EvalContext: Sized {
|
|||||||
f: impl FnOnce(&mut Self) -> T,
|
f: impl FnOnce(&mut Self) -> T,
|
||||||
) -> (Vec<Value<Self>>, T);
|
) -> (Vec<Value<Self>>, T);
|
||||||
fn lookup_with<'a>(&'a self, ident: &str) -> Option<&'a Value<Self>>;
|
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 pop_frame(&mut self) -> Vec<Value<Self>>;
|
||||||
|
fn consume_arg(&mut self, func: ExprId) -> Result<bool>;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait Evaluate<Ctx: EvalContext> {
|
pub trait Evaluate<Ctx: EvalContext> {
|
||||||
@@ -39,7 +41,38 @@ impl<Ctx: EvalContext> Evaluate<Ctx> for ExprId {
|
|||||||
|
|
||||||
impl<Ctx: EvalContext> Evaluate<Ctx> for lir::Lir {
|
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<Ctx>> {
|
||||||
todo!()
|
use lir::Lir::*;
|
||||||
|
match self {
|
||||||
|
AttrSet(x) => x.eval(ctx),
|
||||||
|
List(x) => x.eval(ctx),
|
||||||
|
HasAttr(x) => x.eval(ctx),
|
||||||
|
BinOp(x) => x.eval(ctx),
|
||||||
|
UnOp(x) => x.eval(ctx),
|
||||||
|
Select(x) => x.eval(ctx),
|
||||||
|
If(x) => x.eval(ctx),
|
||||||
|
Call(x) => x.eval(ctx),
|
||||||
|
With(x) => x.eval(ctx),
|
||||||
|
Assert(x) => x.eval(ctx),
|
||||||
|
ConcatStrings(x) => x.eval(ctx),
|
||||||
|
Const(x) => x.eval(ctx),
|
||||||
|
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()))
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -243,7 +276,15 @@ impl<Ctx: EvalContext> Evaluate<Ctx> for ir::With {
|
|||||||
|
|
||||||
impl<Ctx: EvalContext> Evaluate<Ctx> for ir::Assert {
|
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<Ctx>> {
|
||||||
todo!()
|
let cond = self.assertion.eval(ctx)?;
|
||||||
|
let cond = cond
|
||||||
|
.try_unwrap_bool()
|
||||||
|
.map_err(|_| Error::EvalError(format!("expected a boolean but found ...")))?;
|
||||||
|
if cond {
|
||||||
|
self.expr.eval(ctx)
|
||||||
|
} else {
|
||||||
|
Err(Error::EvalError("assertion failed".to_string()))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -142,7 +142,7 @@ impl<Ctx: EvalContext> PartialEq for Value<Ctx> {
|
|||||||
|
|
||||||
impl<Ctx: EvalContext> Eq for Value<Ctx> {}
|
impl<Ctx: EvalContext> Eq for Value<Ctx> {}
|
||||||
|
|
||||||
#[derive(IsVariant, Unwrap, Clone)]
|
#[derive(IsVariant, TryUnwrap, Unwrap, Clone)]
|
||||||
pub enum ValueAsRef<'v, Ctx: EvalContext> {
|
pub enum ValueAsRef<'v, Ctx: EvalContext> {
|
||||||
Int(i64),
|
Int(i64),
|
||||||
Float(f64),
|
Float(f64),
|
||||||
|
|||||||
@@ -316,13 +316,7 @@ impl<Ctx: DowngradeContext> Downgrade<Ctx> for ast::Lambda {
|
|||||||
allowed = if ellipsis {
|
allowed = if ellipsis {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
Some(
|
Some(formals.into_iter().map(|(k, _)| k).collect())
|
||||||
formals
|
|
||||||
.into_iter()
|
|
||||||
.filter(|(_, default)| default.is_some())
|
|
||||||
.map(|(k, _)| k)
|
|
||||||
.collect(),
|
|
||||||
)
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,24 +12,61 @@
|
|||||||
use rnix::ast;
|
use rnix::ast;
|
||||||
|
|
||||||
use derive_more::TryUnwrap;
|
use derive_more::TryUnwrap;
|
||||||
use hashbrown::HashMap;
|
use hashbrown::{HashMap, HashSet};
|
||||||
|
|
||||||
use nixjit_value::Const as PubConst;
|
use nixjit_value::Const as PubConst;
|
||||||
|
|
||||||
/// A type-safe wrapper for an index into an expression table.
|
/// A type-safe wrapper for an index into an expression table.
|
||||||
#[repr(transparent)]
|
#[repr(transparent)]
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
pub struct ExprId(usize);
|
pub struct ExprId(usize);
|
||||||
|
|
||||||
|
impl From<usize> for ExprId {
|
||||||
|
fn from(id: usize) -> Self {
|
||||||
|
ExprId(id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<ExprId> for usize {
|
||||||
|
fn from(id: ExprId) -> Self {
|
||||||
|
id.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// A type-safe wrapper for an index into a function table.
|
/// A type-safe wrapper for an index into a function table.
|
||||||
#[repr(transparent)]
|
#[repr(transparent)]
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
pub struct FuncId(usize);
|
pub struct FuncId(usize);
|
||||||
|
|
||||||
|
impl From<usize> for FuncId {
|
||||||
|
fn from(id: usize) -> Self {
|
||||||
|
FuncId(id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<FuncId> for usize {
|
||||||
|
fn from(id: FuncId) -> Self {
|
||||||
|
id.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A type-safe wrapper for an index into a function's argument list.
|
||||||
#[repr(transparent)]
|
#[repr(transparent)]
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
pub struct ArgIdx(usize);
|
pub struct ArgIdx(usize);
|
||||||
|
|
||||||
|
impl From<usize> for ArgIdx {
|
||||||
|
fn from(id: usize) -> Self {
|
||||||
|
ArgIdx(id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<ArgIdx> for usize {
|
||||||
|
fn from(id: ArgIdx) -> Self {
|
||||||
|
id.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Represents a Nix attribute set.
|
/// Represents a Nix attribute set.
|
||||||
#[derive(Debug, Default)]
|
#[derive(Debug, Default)]
|
||||||
pub struct AttrSet {
|
pub struct AttrSet {
|
||||||
@@ -185,7 +222,7 @@ pub struct Func {
|
|||||||
pub struct Param {
|
pub struct Param {
|
||||||
pub ident: Option<String>,
|
pub ident: Option<String>,
|
||||||
pub required: Option<Vec<String>>,
|
pub required: Option<Vec<String>>,
|
||||||
pub allowed: Option<Vec<String>>,
|
pub allowed: Option<HashSet<String>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Represents a function call.
|
/// Represents a function call.
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ pub extern "C" fn helper_lookup_arg<Ctx: JITContext>(
|
|||||||
offset: usize,
|
offset: usize,
|
||||||
ret: &mut MaybeUninit<Value<Ctx>>,
|
ret: &mut MaybeUninit<Value<Ctx>>,
|
||||||
) {
|
) {
|
||||||
ret.write(ctx.lookup_arg(offset).clone());
|
ret.write(JITContext::lookup_arg(ctx, offset).clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
pub extern "C" fn helper_lookup<Ctx: JITContext>(
|
pub extern "C" fn helper_lookup<Ctx: JITContext>(
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ ir! {
|
|||||||
ArgRef(ArgIdx),
|
ArgRef(ArgIdx),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy)]
|
||||||
pub enum LookupResult {
|
pub enum LookupResult {
|
||||||
Expr(ExprId),
|
Expr(ExprId),
|
||||||
Arg(ArgIdx),
|
Arg(ArgIdx),
|
||||||
|
|||||||
Reference in New Issue
Block a user