feat: initial parallel impl
This commit is contained in:
250
src/eval/mod.rs
250
src/eval/mod.rs
@@ -1,141 +1,285 @@
|
||||
use crate::ty::common::Const;
|
||||
use crate::ty::internal::Value;
|
||||
use crate::ir::{self, Downgraded};
|
||||
use crate::ty::public as p;
|
||||
use crate::error::Result;
|
||||
use std::rc::Rc;
|
||||
|
||||
use ecow::EcoVec;
|
||||
|
||||
use crate::engine::Engine;
|
||||
use crate::env::VmEnv;
|
||||
use crate::error::{Error, Result};
|
||||
use crate::ir::{self, DynamicAttrPair};
|
||||
use crate::ty::common::Const;
|
||||
use crate::ty::internal::{AttrSet, List, Thunk, ThunkRef, Value};
|
||||
use crate::ty::public::Symbol;
|
||||
|
||||
pub mod jit;
|
||||
|
||||
pub trait Evaluate {
|
||||
fn eval<'a>(self, engine: &'a Engine) -> Result<Value<'a>>;
|
||||
fn eval(self, engine: &Engine, env: &VmEnv) -> Result<Value>;
|
||||
}
|
||||
|
||||
impl Evaluate for ir::Attrs {
|
||||
fn eval<'a>(self, engine: &'a Engine) -> Result<Value<'a>> {
|
||||
todo!()
|
||||
fn eval(self, engine: &Engine, env: &VmEnv) -> Result<Value> {
|
||||
let mut attrs = AttrSet::new(
|
||||
self.stcs
|
||||
.into_iter()
|
||||
.map(|(k, v)| Ok((k, v.eval(engine, env)?)))
|
||||
.collect::<Result<_>>()?,
|
||||
);
|
||||
for DynamicAttrPair(k, v) in self.dyns {
|
||||
let mut k = k.eval(engine, env)?;
|
||||
k.coerce_to_string();
|
||||
attrs.push_attr(k.unwrap_string(), v.eval(engine, env)?);
|
||||
}
|
||||
Value::AttrSet(attrs.into()).ok()
|
||||
}
|
||||
}
|
||||
|
||||
impl Evaluate for ir::List {
|
||||
fn eval<'a>(self, engine: &'a Engine) -> Result<Value<'a>> {
|
||||
todo!()
|
||||
impl Evaluate for ir::List {
|
||||
fn eval(self, engine: &Engine, env: &VmEnv) -> Result<Value> {
|
||||
Value::List(List::from(
|
||||
self.items
|
||||
.into_iter()
|
||||
.map(|val| val.eval(engine, env))
|
||||
.collect::<Result<EcoVec<_>>>()?,
|
||||
))
|
||||
.ok()
|
||||
}
|
||||
}
|
||||
|
||||
impl Evaluate for ir::HasAttr {
|
||||
fn eval<'a>(self, engine: &'a Engine) -> Result<Value<'a>> {
|
||||
todo!()
|
||||
fn eval(self, engine: &Engine, env: &VmEnv) -> Result<Value> {
|
||||
use ir::Attr::*;
|
||||
let mut val = self.lhs.eval(engine, env)?;
|
||||
val.has_attr(self.rhs.into_iter().map(|attr| {
|
||||
Ok(match attr {
|
||||
Str(ident) => ident,
|
||||
Strs(expr) => expr.eval(engine, env)?.unwrap_string(),
|
||||
Dynamic(expr) => {
|
||||
let mut val = expr.eval(engine, env)?;
|
||||
val.coerce_to_string();
|
||||
val.unwrap_string()
|
||||
}
|
||||
})
|
||||
}))?;
|
||||
val.ok()
|
||||
}
|
||||
}
|
||||
|
||||
impl Evaluate for ir::BinOp {
|
||||
fn eval<'a>(self, engine: &'a Engine) -> Result<Value<'a>> {
|
||||
todo!()
|
||||
fn eval(self, engine: &Engine, env: &VmEnv) -> Result<Value> {
|
||||
use ir::BinOpKind::*;
|
||||
let mut lhs = self.lhs.eval(engine, env)?;
|
||||
let mut rhs = self.rhs.eval(engine, env)?;
|
||||
match self.kind {
|
||||
Add => lhs.add(rhs),
|
||||
Sub => {
|
||||
rhs.neg();
|
||||
lhs.add(rhs);
|
||||
}
|
||||
Mul => lhs.mul(rhs),
|
||||
Div => lhs.div(rhs)?,
|
||||
Eq => Value::eq(&mut lhs, rhs),
|
||||
Neq => {
|
||||
Value::eq(&mut lhs, rhs);
|
||||
lhs.not();
|
||||
}
|
||||
Lt => lhs.lt(rhs),
|
||||
Gt => {
|
||||
rhs.lt(lhs);
|
||||
lhs = rhs;
|
||||
}
|
||||
Leq => {
|
||||
rhs.lt(lhs);
|
||||
rhs.not();
|
||||
lhs = rhs;
|
||||
}
|
||||
Geq => {
|
||||
lhs.lt(rhs);
|
||||
lhs.not();
|
||||
}
|
||||
And => lhs.and(rhs),
|
||||
Or => lhs.or(rhs),
|
||||
Impl => {
|
||||
lhs.not();
|
||||
lhs.or(rhs);
|
||||
}
|
||||
Con => lhs.concat(rhs),
|
||||
Upd => lhs.update(rhs),
|
||||
PipeL => lhs.call(rhs, engine)?,
|
||||
PipeR => {
|
||||
rhs.call(lhs, engine)?;
|
||||
lhs = rhs;
|
||||
}
|
||||
}
|
||||
Ok(lhs)
|
||||
}
|
||||
}
|
||||
|
||||
impl Evaluate for ir::UnOp {
|
||||
fn eval<'a>(self, engine: &'a Engine) -> Result<Value<'a>> {
|
||||
todo!()
|
||||
impl Evaluate for ir::UnOp {
|
||||
fn eval(self, engine: &Engine, env: &VmEnv) -> Result<Value> {
|
||||
use ir::UnOpKind::*;
|
||||
let mut rhs = self.rhs.eval(engine, env)?;
|
||||
match self.kind {
|
||||
Neg => rhs.neg(),
|
||||
Not => rhs.not(),
|
||||
}
|
||||
Ok(rhs)
|
||||
}
|
||||
}
|
||||
|
||||
impl Evaluate for ir::Select {
|
||||
fn eval<'a>(self, engine: &'a Engine) -> Result<Value<'a>> {
|
||||
todo!()
|
||||
fn eval(self, engine: &Engine, env: &VmEnv) -> Result<Value> {
|
||||
use ir::Attr::*;
|
||||
let mut val = self.expr.eval(engine, env)?;
|
||||
if let Some(default) = self.default {
|
||||
val.select_with_default(
|
||||
self.attrpath.into_iter().map(|attr| {
|
||||
Ok(match attr {
|
||||
Str(ident) => ident,
|
||||
Strs(expr) => expr.eval(engine, env)?.unwrap_string(),
|
||||
Dynamic(expr) => {
|
||||
let mut val = expr.eval(engine, env)?;
|
||||
val.coerce_to_string();
|
||||
val.unwrap_string()
|
||||
}
|
||||
})
|
||||
}),
|
||||
default.eval(engine, env)?,
|
||||
)?;
|
||||
} else {
|
||||
val.select(self.attrpath.into_iter().map(|attr| {
|
||||
Ok(match attr {
|
||||
Str(ident) => ident,
|
||||
Strs(expr) => expr.eval(engine, env)?.unwrap_string(),
|
||||
Dynamic(expr) => {
|
||||
let mut val = expr.eval(engine, env)?;
|
||||
val.coerce_to_string();
|
||||
val.unwrap_string()
|
||||
}
|
||||
})
|
||||
}))?;
|
||||
}
|
||||
val.ok()
|
||||
}
|
||||
}
|
||||
|
||||
impl Evaluate for ir::If {
|
||||
fn eval<'a>(self, engine: &'a Engine) -> Result<Value<'a>> {
|
||||
todo!()
|
||||
fn eval(self, engine: &Engine, env: &VmEnv) -> Result<Value> {
|
||||
// TODO: Error Handling
|
||||
let cond = self.cond.eval(engine, env)?.unwrap_bool();
|
||||
if cond {
|
||||
self.consq.eval(engine, env)
|
||||
} else {
|
||||
self.alter.eval(engine, env)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Evaluate for ir::LoadFunc {
|
||||
fn eval<'a>(self, engine: &'a Engine) -> Result<Value<'a>> {
|
||||
todo!()
|
||||
fn eval(self, _: &Engine, _: &VmEnv) -> Result<Value> {
|
||||
Value::Func(Rc::new(ThunkRef::new(self.idx).into())).ok()
|
||||
}
|
||||
}
|
||||
|
||||
impl Evaluate for ir::Call {
|
||||
fn eval<'a>(self, engine: &'a Engine) -> Result<Value<'a>> {
|
||||
todo!()
|
||||
fn eval(self, engine: &Engine, env: &VmEnv) -> Result<Value> {
|
||||
let mut func = self.func.eval(engine, env)?;
|
||||
// FIXME: Modify Value::call
|
||||
for arg in self.args {
|
||||
func.call(arg.eval(engine, env)?, engine)?;
|
||||
}
|
||||
func.ok()
|
||||
}
|
||||
}
|
||||
|
||||
impl Evaluate for ir::Let {
|
||||
fn eval<'a>(self, engine: &'a Engine) -> Result<Value<'a>> {
|
||||
todo!()
|
||||
fn eval(self, engine: &Engine, env: &VmEnv) -> Result<Value> {
|
||||
let bindings = self.bindings.into_iter().map(|(_, v)| Ok(v.eval(engine, env)?)).collect::<Result<Vec<_>>>()?;
|
||||
self.expr.eval(engine, &env.enter_let(bindings))
|
||||
}
|
||||
}
|
||||
|
||||
impl Evaluate for ir::With {
|
||||
fn eval<'a>(self, engine: &'a Engine) -> Result<Value<'a>> {
|
||||
todo!()
|
||||
fn eval(self, engine: &Engine, env: &VmEnv) -> Result<Value> {
|
||||
let namespace = self.namespace.eval(engine, env)?;
|
||||
// TODO: Error Handling
|
||||
self.expr.eval(engine, &env.enter_with(namespace.unwrap_attr_set().into_inner()))
|
||||
}
|
||||
}
|
||||
|
||||
impl Evaluate for ir::Assert {
|
||||
fn eval<'a>(self, engine: &'a Engine) -> Result<Value<'a>> {
|
||||
fn eval(self, engine: &Engine, env: &VmEnv) -> Result<Value> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
impl Evaluate for ir::ConcatStrings {
|
||||
fn eval<'a>(self, engine: &'a Engine) -> Result<Value<'a>> {
|
||||
todo!()
|
||||
fn eval(self, engine: &Engine, env: &VmEnv) -> Result<Value> {
|
||||
let mut parts = self
|
||||
.parts
|
||||
.into_iter()
|
||||
.map(|part| {
|
||||
let mut part = part.eval(engine, env)?;
|
||||
part.coerce_to_string();
|
||||
part.ok()
|
||||
})
|
||||
.collect::<Result<Vec<_>>>()?
|
||||
.into_iter();
|
||||
let init = parts.next().unwrap();
|
||||
parts
|
||||
.fold(init, |mut a, b| {
|
||||
a.concat_string(b);
|
||||
a
|
||||
})
|
||||
.ok()
|
||||
}
|
||||
}
|
||||
|
||||
impl Evaluate for ir::String {
|
||||
fn eval<'a>(self, engine: &'a Engine) -> Result<Value<'a>> {
|
||||
todo!()
|
||||
fn eval(self, _: &Engine, _: &VmEnv) -> Result<Value> {
|
||||
Value::String(self.val).ok()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl Evaluate for ir::Const {
|
||||
fn eval<'a>(self, _: &'a Engine) -> Result<Value<'a>> {
|
||||
fn eval(self, _: &Engine, _: &VmEnv) -> Result<Value> {
|
||||
match self.val {
|
||||
Const::Null => Value::Null,
|
||||
Const::Int(x) => Value::Int(x),
|
||||
Const::Float(x) => Value::Float(x),
|
||||
Const::Bool(x) => Value::Bool(x),
|
||||
}.ok()
|
||||
}
|
||||
.ok()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl Evaluate for ir::Var {
|
||||
fn eval<'a>(self, engine: &'a Engine) -> Result<Value<'a>> {
|
||||
todo!()
|
||||
fn eval(self, _: &Engine, env: &VmEnv) -> Result<Value> {
|
||||
env.lookup_with(&self.sym)
|
||||
.cloned()
|
||||
.ok_or_else(|| Error::EvalError(format!("{} not found", Symbol::from(self.sym))))
|
||||
}
|
||||
}
|
||||
|
||||
impl Evaluate for ir::Arg {
|
||||
fn eval<'a>(self, engine: &'a Engine) -> Result<Value<'a>> {
|
||||
todo!()
|
||||
fn eval(self, _: &Engine, env: &VmEnv) -> Result<Value> {
|
||||
env.lookup_arg(self.level).clone().ok()
|
||||
}
|
||||
}
|
||||
|
||||
impl Evaluate for ir::LetVar {
|
||||
fn eval<'a>(self, engine: &'a Engine) -> Result<Value<'a>> {
|
||||
todo!()
|
||||
fn eval(self, _: &Engine, env: &VmEnv) -> Result<Value> {
|
||||
env.lookup_let(self.level, self.idx).clone().ok()
|
||||
}
|
||||
}
|
||||
|
||||
impl Evaluate for ir::Thunk {
|
||||
fn eval<'a>(self, engine: &'a Engine) -> Result<Value<'a>> {
|
||||
todo!()
|
||||
fn eval(self, _: &Engine, _: &VmEnv) -> Result<Value> {
|
||||
Value::Thunk(Rc::new(Thunk::new(self.idx).into())).ok()
|
||||
}
|
||||
}
|
||||
|
||||
impl Evaluate for ir::Path {
|
||||
fn eval<'a>(self, engine: &'a Engine) -> Result<Value<'a>> {
|
||||
todo!()
|
||||
fn eval(self, engine: &Engine, env: &VmEnv) -> Result<Value> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn eval(expr: Downgraded) -> Result<p::Value> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user