chore: eliminate Result::unwrap
This commit is contained in:
1
Cargo.lock
generated
1
Cargo.lock
generated
@@ -1941,6 +1941,7 @@ dependencies = [
|
||||
"serde_json",
|
||||
"sha2",
|
||||
"string-interner",
|
||||
"tap",
|
||||
"tar",
|
||||
"tempfile",
|
||||
"thiserror 2.0.18",
|
||||
|
||||
8
Justfile
8
Justfile
@@ -1,15 +1,15 @@
|
||||
[no-exit-message]
|
||||
@repl:
|
||||
RUST_LOG=none cargo run --bin repl
|
||||
cargo run --bin repl
|
||||
|
||||
[no-exit-message]
|
||||
@eval expr:
|
||||
RUST_LOG=none cargo run --bin eval -- '{{expr}}'
|
||||
cargo run --bin eval -- '{{expr}}'
|
||||
|
||||
[no-exit-message]
|
||||
@replr:
|
||||
RUST_LOG=none cargo run --bin repl --release
|
||||
cargo run --bin repl --release
|
||||
|
||||
[no-exit-message]
|
||||
@evalr expr:
|
||||
RUST_LOG=none cargo run --bin eval --release -- '{{expr}}'
|
||||
cargo run --bin eval --release -- '{{expr}}'
|
||||
|
||||
@@ -59,6 +59,7 @@ rowan = "0.16"
|
||||
nix-js-macros = { path = "../nix-js-macros" }
|
||||
ere = "0.2.4"
|
||||
num_enum = "0.7.5"
|
||||
tap = "1.0.1"
|
||||
|
||||
[dev-dependencies]
|
||||
criterion = { version = "0.8", features = ["html_reports"] }
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
mod utils;
|
||||
|
||||
use std::hint::black_box;
|
||||
use criterion::{Criterion, criterion_group, criterion_main};
|
||||
use std::hint::black_box;
|
||||
use utils::eval;
|
||||
|
||||
fn bench_arithmetic(c: &mut Criterion) {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
mod utils;
|
||||
|
||||
use std::hint::black_box;
|
||||
use criterion::{Criterion, criterion_group, criterion_main};
|
||||
use std::hint::black_box;
|
||||
use utils::eval;
|
||||
|
||||
fn bench_builtin_math(c: &mut Criterion) {
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
mod utils;
|
||||
|
||||
use std::hint::black_box;
|
||||
use criterion::{Criterion, criterion_group, criterion_main};
|
||||
use nix_js::context::Context;
|
||||
use std::hint::black_box;
|
||||
use utils::compile;
|
||||
|
||||
fn bench_parse_and_downgrade(c: &mut Criterion) {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
mod utils;
|
||||
|
||||
use std::hint::black_box;
|
||||
use criterion::{Criterion, criterion_group, criterion_main};
|
||||
use std::hint::black_box;
|
||||
use utils::eval;
|
||||
|
||||
fn bench_non_recursive(c: &mut Criterion) {
|
||||
|
||||
@@ -2,11 +2,10 @@ use std::path::Path;
|
||||
use std::ptr::NonNull;
|
||||
|
||||
use hashbrown::{HashMap, HashSet};
|
||||
use itertools::Itertools as _;
|
||||
use rnix::TextRange;
|
||||
use string_interner::DefaultStringInterner;
|
||||
|
||||
use crate::codegen::{CodegenContext, compile};
|
||||
use crate::codegen::{CodegenContext, compile, compile_scoped};
|
||||
use crate::downgrade::*;
|
||||
use crate::error::{Error, Result, Source};
|
||||
use crate::ir::{
|
||||
@@ -17,6 +16,34 @@ use crate::runtime::{Runtime, RuntimeContext};
|
||||
use crate::store::{DaemonStore, Store, StoreConfig};
|
||||
use crate::value::{Symbol, Value};
|
||||
|
||||
fn parse_error_span(error: &rnix::ParseError) -> Option<rnix::TextRange> {
|
||||
use rnix::ParseError::*;
|
||||
match error {
|
||||
Unexpected(range)
|
||||
| UnexpectedExtra(range)
|
||||
| UnexpectedWanted(_, range, _)
|
||||
| UnexpectedDoubleBind(range)
|
||||
| DuplicatedArgs(range, _) => Some(*range),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_parse_error<'a>(
|
||||
errors: impl IntoIterator<Item = &'a rnix::ParseError>,
|
||||
source: Source,
|
||||
) -> Option<Box<Error>> {
|
||||
for err in errors {
|
||||
if let Some(span) = parse_error_span(err) {
|
||||
return Some(
|
||||
Error::parse_error(err.to_string())
|
||||
.with_source(source)
|
||||
.with_span(span),
|
||||
);
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
pub struct Context {
|
||||
ctx: Ctx,
|
||||
runtime: Runtime<Ctx>,
|
||||
@@ -232,23 +259,24 @@ impl Ctx {
|
||||
self.sources.get(id).expect("source not found").clone()
|
||||
}
|
||||
|
||||
fn compile<'a>(&'a mut self, source: Source, extra_scope: Option<Scope<'a>>) -> Result<String> {
|
||||
fn downgrade<'a>(&mut self, source: Source, extra_scope: Option<Scope<'a>>) -> Result<ExprId> {
|
||||
tracing::debug!("Parsing Nix expression");
|
||||
|
||||
self.sources.push(source.clone());
|
||||
|
||||
let root = rnix::Root::parse(&source.src);
|
||||
if !root.errors().is_empty() {
|
||||
let error_msg = root.errors().iter().join("; ");
|
||||
let err = Error::parse_error(error_msg).with_source(source);
|
||||
return Err(err);
|
||||
}
|
||||
handle_parse_error(root.errors(), source).map_or(Ok(()), Err)?;
|
||||
|
||||
#[allow(clippy::unwrap_used)]
|
||||
let root = self
|
||||
.downgrade_ctx(extra_scope)
|
||||
.downgrade(root.tree().expr().unwrap())?;
|
||||
tracing::debug!("Downgrading Nix expression");
|
||||
let expr = root
|
||||
.tree()
|
||||
.expr()
|
||||
.ok_or_else(|| Error::parse_error("unexpected EOF".into()))?;
|
||||
self.downgrade_ctx(extra_scope).downgrade(expr)
|
||||
}
|
||||
|
||||
fn compile<'a>(&'a mut self, source: Source, extra_scope: Option<Scope<'a>>) -> Result<String> {
|
||||
let root = self.downgrade(source, extra_scope)?;
|
||||
tracing::debug!("Generating JavaScript code");
|
||||
let code = compile(self.get_ir(root), self);
|
||||
tracing::debug!("Generated code: {}", &code);
|
||||
@@ -256,31 +284,13 @@ impl Ctx {
|
||||
}
|
||||
|
||||
pub(crate) fn compile_scoped(&mut self, source: Source, scope: Vec<String>) -> Result<String> {
|
||||
use crate::codegen::compile_scoped;
|
||||
|
||||
tracing::debug!("Parsing Nix expression for scoped import");
|
||||
|
||||
self.sources.push(source.clone());
|
||||
|
||||
let root = rnix::Root::parse(&source.src);
|
||||
if !root.errors().is_empty() {
|
||||
let error_msg = root.errors().iter().join("; ");
|
||||
let err = Error::parse_error(error_msg).with_source(source);
|
||||
return Err(err);
|
||||
}
|
||||
|
||||
let scope = Scope::ScopedImport(
|
||||
scope
|
||||
.into_iter()
|
||||
.map(|k| self.symbols.get_or_intern(k))
|
||||
.collect(),
|
||||
);
|
||||
|
||||
#[allow(clippy::unwrap_used)]
|
||||
let root = self
|
||||
.downgrade_ctx(Some(scope))
|
||||
.downgrade(root.tree().expr().unwrap())?;
|
||||
|
||||
let root = self.downgrade(source, Some(scope))?;
|
||||
tracing::debug!("Generating JavaScript code for scoped import");
|
||||
let code = compile_scoped(self.get_ir(root), self);
|
||||
tracing::debug!("Generated scoped code: {}", &code);
|
||||
|
||||
@@ -1,17 +1,41 @@
|
||||
// Assume no parse error
|
||||
#![allow(clippy::unwrap_used)]
|
||||
|
||||
use hashbrown::hash_map::Entry;
|
||||
use hashbrown::{HashMap, HashSet};
|
||||
use itertools::Itertools as _;
|
||||
use rnix::TextRange;
|
||||
use rnix::ast::{self, AstToken, Expr, HasEntry};
|
||||
use rowan::ast::AstNode;
|
||||
use tap::TryConv;
|
||||
|
||||
use crate::error::{Error, Result, Source};
|
||||
use crate::ir::*;
|
||||
use crate::value::Symbol;
|
||||
|
||||
trait Require<T> {
|
||||
fn require(self, ctx: &impl DowngradeContext, span: TextRange) -> Result<T>;
|
||||
}
|
||||
|
||||
impl<T> Require<T> for Option<T> {
|
||||
#[inline]
|
||||
fn require(self, ctx: &impl DowngradeContext, span: TextRange) -> Result<T> {
|
||||
self.ok_or_else(|| {
|
||||
Error::parse_error("invalid syntax".into())
|
||||
.with_source(ctx.get_current_source())
|
||||
.with_span(span)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, E: std::fmt::Display> Require<T> for std::result::Result<T, E> {
|
||||
#[inline]
|
||||
fn require(self, ctx: &impl DowngradeContext, span: TextRange) -> Result<T> {
|
||||
self.map_err(|e| {
|
||||
Error::parse_error(format!("invalid syntax: {e}"))
|
||||
.with_source(ctx.get_current_source())
|
||||
.with_span(span)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub trait DowngradeContext {
|
||||
fn downgrade(self, expr: rnix::ast::Expr) -> Result<ExprId>;
|
||||
|
||||
@@ -79,19 +103,25 @@ impl<Ctx: DowngradeContext> Downgrade<Ctx> for Expr {
|
||||
Ident(ident) => ident.downgrade(ctx),
|
||||
With(with) => with.downgrade(ctx),
|
||||
HasAttr(has) => has.downgrade(ctx),
|
||||
Paren(paren) => paren.expr().unwrap().downgrade(ctx),
|
||||
Root(root) => root.expr().unwrap().downgrade(ctx),
|
||||
Paren(paren) => paren
|
||||
.expr()
|
||||
.require(ctx, paren.syntax().text_range())?
|
||||
.downgrade(ctx),
|
||||
Root(root) => root
|
||||
.expr()
|
||||
.require(ctx, root.syntax().text_range())?
|
||||
.downgrade(ctx),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<Ctx: DowngradeContext> Downgrade<Ctx> for ast::Assert {
|
||||
fn downgrade(self, ctx: &mut Ctx) -> Result<ExprId> {
|
||||
let assertion = self.condition().unwrap();
|
||||
let span = self.syntax().text_range();
|
||||
let assertion = self.condition().require(ctx, span)?;
|
||||
let assertion_raw = assertion.to_string();
|
||||
let assertion = assertion.downgrade(ctx)?;
|
||||
let expr = self.body().unwrap().downgrade(ctx)?;
|
||||
let span = self.syntax().text_range();
|
||||
let expr = self.body().require(ctx, span)?.downgrade(ctx)?;
|
||||
Ok(ctx.new_expr(
|
||||
Assert {
|
||||
assertion,
|
||||
@@ -106,10 +136,10 @@ impl<Ctx: DowngradeContext> Downgrade<Ctx> for ast::Assert {
|
||||
|
||||
impl<Ctx: DowngradeContext> Downgrade<Ctx> for ast::IfElse {
|
||||
fn downgrade(self, ctx: &mut Ctx) -> Result<ExprId> {
|
||||
let cond = self.condition().unwrap().downgrade(ctx)?;
|
||||
let consq = self.body().unwrap().downgrade(ctx)?;
|
||||
let alter = self.else_body().unwrap().downgrade(ctx)?;
|
||||
let span = self.syntax().text_range();
|
||||
let cond = self.condition().require(ctx, span)?.downgrade(ctx)?;
|
||||
let consq = self.body().require(ctx, span)?.downgrade(ctx)?;
|
||||
let alter = self.else_body().require(ctx, span)?.downgrade(ctx)?;
|
||||
Ok(ctx.new_expr(
|
||||
If {
|
||||
cond,
|
||||
@@ -139,7 +169,7 @@ impl<Ctx: DowngradeContext> Downgrade<Ctx> for ast::PathSearch {
|
||||
fn downgrade(self, ctx: &mut Ctx) -> Result<ExprId> {
|
||||
let span = self.syntax().text_range();
|
||||
let path = {
|
||||
let temp = self.content().unwrap();
|
||||
let temp = self.content().require(ctx, span)?;
|
||||
let text = temp.text();
|
||||
ctx.new_expr(
|
||||
Str {
|
||||
@@ -184,14 +214,17 @@ impl<Ctx: DowngradeContext> Downgrade<Ctx> for ast::Str {
|
||||
.map(|part| match part {
|
||||
ast::InterpolPart::Literal(lit) => Ok(ctx.new_expr(Str { val: lit, span }.to_ir())),
|
||||
ast::InterpolPart::Interpolation(interpol) => {
|
||||
let inner = interpol.expr().unwrap().downgrade(ctx)?;
|
||||
let inner = interpol
|
||||
.expr()
|
||||
.require(ctx, interpol.syntax().text_range())?
|
||||
.downgrade(ctx)?;
|
||||
Ok(ctx.maybe_thunk(inner))
|
||||
}
|
||||
})
|
||||
.collect::<Result<Vec<_>>>()?;
|
||||
|
||||
Ok(if is_single_literal {
|
||||
parts.into_iter().next().unwrap()
|
||||
parts.into_iter().next().expect("is_single_literal checked")
|
||||
} else {
|
||||
ctx.new_expr(
|
||||
ConcatStrings {
|
||||
@@ -210,12 +243,12 @@ impl<Ctx: DowngradeContext> Downgrade<Ctx> for ast::Literal {
|
||||
let span = self.syntax().text_range();
|
||||
Ok(ctx.new_expr(match self.kind() {
|
||||
ast::LiteralKind::Integer(int) => Int {
|
||||
inner: int.value().unwrap(),
|
||||
inner: int.value().require(ctx, span)?,
|
||||
span,
|
||||
}
|
||||
.to_ir(),
|
||||
ast::LiteralKind::Float(float) => Float {
|
||||
inner: float.value().unwrap(),
|
||||
inner: float.value().require(ctx, span)?,
|
||||
span,
|
||||
}
|
||||
.to_ir(),
|
||||
@@ -230,8 +263,8 @@ impl<Ctx: DowngradeContext> Downgrade<Ctx> for ast::Literal {
|
||||
|
||||
impl<Ctx: DowngradeContext> Downgrade<Ctx> for ast::Ident {
|
||||
fn downgrade(self, ctx: &mut Ctx) -> Result<ExprId> {
|
||||
let text = self.ident_token().unwrap().to_string();
|
||||
let span = self.syntax().text_range();
|
||||
let text = self.ident_token().require(ctx, span)?.to_string();
|
||||
|
||||
if text == "__curPos" {
|
||||
return Ok(ctx.new_expr(CurPos { span }.to_ir()));
|
||||
@@ -276,10 +309,10 @@ impl<Ctx: DowngradeContext> Downgrade<Ctx> for ast::List {
|
||||
/// Downgrades a binary operation.
|
||||
impl<Ctx: DowngradeContext> Downgrade<Ctx> for ast::BinOp {
|
||||
fn downgrade(self, ctx: &mut Ctx) -> Result<ExprId> {
|
||||
let lhs = self.lhs().unwrap().downgrade(ctx)?;
|
||||
let rhs = self.rhs().unwrap().downgrade(ctx)?;
|
||||
let kind = self.operator().unwrap().into();
|
||||
let span = self.syntax().text_range();
|
||||
let lhs = self.lhs().require(ctx, span)?.downgrade(ctx)?;
|
||||
let rhs = self.rhs().require(ctx, span)?.downgrade(ctx)?;
|
||||
let kind = self.operator().require(ctx, span)?.into();
|
||||
Ok(ctx.new_expr(
|
||||
BinOp {
|
||||
lhs,
|
||||
@@ -295,9 +328,9 @@ impl<Ctx: DowngradeContext> Downgrade<Ctx> for ast::BinOp {
|
||||
/// Downgrades a "has attribute" (`?`) expression.
|
||||
impl<Ctx: DowngradeContext> Downgrade<Ctx> for ast::HasAttr {
|
||||
fn downgrade(self, ctx: &mut Ctx) -> Result<ExprId> {
|
||||
let lhs = self.expr().unwrap().downgrade(ctx)?;
|
||||
let rhs = downgrade_attrpath(self.attrpath().unwrap(), ctx)?;
|
||||
let span = self.syntax().text_range();
|
||||
let lhs = self.expr().require(ctx, span)?.downgrade(ctx)?;
|
||||
let rhs = downgrade_attrpath(self.attrpath().require(ctx, span)?, ctx)?;
|
||||
Ok(ctx.new_expr(HasAttr { lhs, rhs, span }.to_ir()))
|
||||
}
|
||||
}
|
||||
@@ -305,9 +338,9 @@ impl<Ctx: DowngradeContext> Downgrade<Ctx> for ast::HasAttr {
|
||||
/// Downgrades a unary operation.
|
||||
impl<Ctx: DowngradeContext> Downgrade<Ctx> for ast::UnaryOp {
|
||||
fn downgrade(self, ctx: &mut Ctx) -> Result<ExprId> {
|
||||
let rhs = self.expr().unwrap().downgrade(ctx)?;
|
||||
let kind = self.operator().unwrap().into();
|
||||
let span = self.syntax().text_range();
|
||||
let rhs = self.expr().require(ctx, span)?.downgrade(ctx)?;
|
||||
let kind = self.operator().require(ctx, span)?.into();
|
||||
Ok(ctx.new_expr(UnOp { rhs, kind, span }.to_ir()))
|
||||
}
|
||||
}
|
||||
@@ -315,8 +348,9 @@ impl<Ctx: DowngradeContext> Downgrade<Ctx> for ast::UnaryOp {
|
||||
/// Downgrades an attribute selection (`.`).
|
||||
impl<Ctx: DowngradeContext> Downgrade<Ctx> for ast::Select {
|
||||
fn downgrade(self, ctx: &mut Ctx) -> Result<ExprId> {
|
||||
let expr = self.expr().unwrap().downgrade(ctx)?;
|
||||
let attrpath = downgrade_attrpath(self.attrpath().unwrap(), ctx)?;
|
||||
let span = self.syntax().text_range();
|
||||
let expr = self.expr().require(ctx, span)?.downgrade(ctx)?;
|
||||
let attrpath = downgrade_attrpath(self.attrpath().require(ctx, span)?, ctx)?;
|
||||
let default = if let Some(default) = self.default_expr() {
|
||||
let default_expr = default.downgrade(ctx)?;
|
||||
Some(ctx.maybe_thunk(default_expr))
|
||||
@@ -374,8 +408,8 @@ impl<Ctx: DowngradeContext> Downgrade<Ctx> for ast::LegacyLet {
|
||||
impl<Ctx: DowngradeContext> Downgrade<Ctx> for ast::LetIn {
|
||||
fn downgrade(self, ctx: &mut Ctx) -> Result<ExprId> {
|
||||
let entries: Vec<_> = self.entries().collect();
|
||||
let body_expr = self.body().unwrap();
|
||||
let span = self.syntax().text_range();
|
||||
let body_expr = self.body().require(ctx, span)?;
|
||||
|
||||
downgrade_let_bindings(entries, ctx, span, |ctx, _binding_keys| {
|
||||
body_expr.downgrade(ctx)
|
||||
@@ -387,11 +421,12 @@ impl<Ctx: DowngradeContext> Downgrade<Ctx> for ast::LetIn {
|
||||
impl<Ctx: DowngradeContext> Downgrade<Ctx> for ast::With {
|
||||
fn downgrade(self, ctx: &mut Ctx) -> Result<ExprId> {
|
||||
let span = self.syntax().text_range();
|
||||
let namespace = self.namespace().unwrap().downgrade(ctx)?;
|
||||
let namespace = self.namespace().require(ctx, span)?.downgrade(ctx)?;
|
||||
let namespace = ctx.maybe_thunk(namespace);
|
||||
|
||||
let (body, thunks) = ctx
|
||||
.with_thunk_scope(|ctx| ctx.with_with_scope(|ctx| self.body().unwrap().downgrade(ctx)));
|
||||
let body_expr = self.body().require(ctx, span)?;
|
||||
let (body, thunks) =
|
||||
ctx.with_thunk_scope(|ctx| ctx.with_with_scope(|ctx| body_expr.downgrade(ctx)));
|
||||
let body = body?;
|
||||
|
||||
Ok(ctx.new_expr(
|
||||
@@ -410,7 +445,9 @@ impl<Ctx: DowngradeContext> Downgrade<Ctx> for ast::With {
|
||||
/// This involves desugaring pattern-matching arguments into `let` bindings.
|
||||
impl<Ctx: DowngradeContext> Downgrade<Ctx> for ast::Lambda {
|
||||
fn downgrade(self, ctx: &mut Ctx) -> Result<ExprId> {
|
||||
let raw_param = self.param().unwrap();
|
||||
let span = self.syntax().text_range();
|
||||
let raw_param = self.param().require(ctx, span)?;
|
||||
let body_ast = self.body().require(ctx, span)?;
|
||||
let arg = ctx.new_arg(raw_param.syntax().text_range());
|
||||
|
||||
struct Ret {
|
||||
@@ -424,19 +461,20 @@ impl<Ctx: DowngradeContext> Downgrade<Ctx> for ast::Lambda {
|
||||
|
||||
match raw_param {
|
||||
ast::Param::IdentParam(id) => {
|
||||
// Simple case: `x: body`
|
||||
let param_sym = ctx.new_sym(id.to_string());
|
||||
param = None;
|
||||
|
||||
// Downgrade body in Param scope
|
||||
body = ctx.with_param_scope(param_sym, arg, |ctx| {
|
||||
self.body().unwrap().downgrade(ctx)
|
||||
})?;
|
||||
body = ctx
|
||||
.with_param_scope(param_sym, arg, |ctx| body_ast.clone().downgrade(ctx))?;
|
||||
}
|
||||
ast::Param::Pattern(pattern) => {
|
||||
let alias = pattern
|
||||
.pat_bind()
|
||||
.map(|alias| ctx.new_sym(alias.ident().unwrap().to_string()));
|
||||
.map(|alias| {
|
||||
let ident = alias.ident().require(ctx, alias.syntax().text_range())?;
|
||||
Ok::<_, Box<Error>>(ctx.new_sym(ident.to_string()))
|
||||
})
|
||||
.transpose()?;
|
||||
|
||||
let ellipsis = pattern.ellipsis_token().is_some();
|
||||
let pat_entries = pattern.pat_entries();
|
||||
@@ -446,7 +484,7 @@ impl<Ctx: DowngradeContext> Downgrade<Ctx> for ast::Lambda {
|
||||
required,
|
||||
optional,
|
||||
} = downgrade_pattern_bindings(pat_entries, alias, arg, ctx, |ctx, _| {
|
||||
self.body().unwrap().downgrade(ctx)
|
||||
body_ast.clone().downgrade(ctx)
|
||||
})?;
|
||||
|
||||
param = Some(Param {
|
||||
@@ -463,7 +501,6 @@ impl<Ctx: DowngradeContext> Downgrade<Ctx> for ast::Lambda {
|
||||
});
|
||||
let Ret { param, body } = ret?;
|
||||
|
||||
let span = self.syntax().text_range();
|
||||
Ok(ctx.new_expr(
|
||||
Func {
|
||||
body,
|
||||
@@ -482,8 +519,9 @@ impl<Ctx: DowngradeContext> Downgrade<Ctx> for ast::Lambda {
|
||||
/// Each Apply node represents a single function call with one argument.
|
||||
impl<Ctx: DowngradeContext> Downgrade<Ctx> for ast::Apply {
|
||||
fn downgrade(self, ctx: &mut Ctx) -> Result<ExprId> {
|
||||
let func = self.lambda().unwrap().downgrade(ctx)?;
|
||||
let arg = self.argument().unwrap().downgrade(ctx)?;
|
||||
let span = self.syntax().text_range();
|
||||
let func = self.lambda().require(ctx, span)?.downgrade(ctx)?;
|
||||
let arg = self.argument().require(ctx, span)?.downgrade(ctx)?;
|
||||
let arg = ctx.maybe_thunk(arg);
|
||||
let span = self.syntax().text_range();
|
||||
Ok(ctx.new_expr(Call { func, arg, span }.to_ir()))
|
||||
@@ -535,7 +573,8 @@ impl PendingAttrSet {
|
||||
ast::Attr::Str(string) => {
|
||||
let parts = string.normalized_parts();
|
||||
if parts.len() == 1
|
||||
&& let ast::InterpolPart::Literal(lit) = parts.into_iter().next().unwrap()
|
||||
&& let ast::InterpolPart::Literal(lit) =
|
||||
parts.into_iter().next().expect("len checked")
|
||||
{
|
||||
let sym = ctx.new_sym(lit);
|
||||
return self.insert_static(sym, span, rest, value, ctx);
|
||||
@@ -752,9 +791,10 @@ impl PendingAttrSet {
|
||||
self.collect_inherit(inherit, ctx)?;
|
||||
}
|
||||
ast::Entry::AttrpathValue(value) => {
|
||||
let attrpath = value.attrpath().unwrap();
|
||||
let span = value.syntax().text_range();
|
||||
let attrpath = value.attrpath().require(ctx, span)?;
|
||||
let path: Vec<_> = attrpath.attrs().collect();
|
||||
let expr = value.value().unwrap();
|
||||
let expr = value.value().require(ctx, span)?;
|
||||
self.insert(&path, expr, ctx)?;
|
||||
}
|
||||
}
|
||||
@@ -767,7 +807,13 @@ impl PendingAttrSet {
|
||||
inherit: ast::Inherit,
|
||||
ctx: &mut impl DowngradeContext,
|
||||
) -> Result<()> {
|
||||
let from = inherit.from().map(|f| f.expr().unwrap());
|
||||
let from = inherit
|
||||
.from()
|
||||
.map(|f| {
|
||||
let span = f.syntax().text_range();
|
||||
f.expr().require(ctx, span)
|
||||
})
|
||||
.transpose()?;
|
||||
for attr in inherit.attrs() {
|
||||
let span = attr.syntax().text_range();
|
||||
let sym = match &attr {
|
||||
@@ -775,7 +821,8 @@ impl PendingAttrSet {
|
||||
ast::Attr::Str(s) => {
|
||||
let parts = s.normalized_parts();
|
||||
if parts.len() == 1
|
||||
&& let ast::InterpolPart::Literal(lit) = parts.into_iter().next().unwrap()
|
||||
&& let ast::InterpolPart::Literal(lit) =
|
||||
parts.into_iter().next().expect("len checked")
|
||||
{
|
||||
ctx.new_sym(lit)
|
||||
} else {
|
||||
@@ -870,7 +917,7 @@ fn make_attrpath_value_entry(path: Vec<ast::Attr>, value: ast::Expr) -> ast::Ent
|
||||
|
||||
let green = builder.finish();
|
||||
let node = rowan::SyntaxNode::<NixLanguage>::new_root(green);
|
||||
ast::Entry::cast(node).unwrap()
|
||||
ast::Entry::cast(node).expect("constructed valid Entry node")
|
||||
}
|
||||
|
||||
/// Downgrades the entries of a non-recursive attribute set.
|
||||
@@ -899,10 +946,13 @@ fn downgrade_attr(attr: ast::Attr, ctx: &mut impl DowngradeContext) -> Result<At
|
||||
if parts.is_empty() {
|
||||
Ok(Attr::Str(ctx.new_sym("".to_string()), span))
|
||||
} else if parts.len() == 1 {
|
||||
match parts.into_iter().next().unwrap() {
|
||||
match parts.into_iter().next().expect("len checked") {
|
||||
Literal(ident) => Ok(Attr::Str(ctx.new_sym(ident), span)),
|
||||
Interpolation(interpol) => Ok(Attr::Dynamic(
|
||||
interpol.expr().unwrap().downgrade(ctx)?,
|
||||
interpol
|
||||
.expr()
|
||||
.require(ctx, interpol.syntax().text_range())?
|
||||
.downgrade(ctx)?,
|
||||
span,
|
||||
)),
|
||||
}
|
||||
@@ -911,7 +961,10 @@ fn downgrade_attr(attr: ast::Attr, ctx: &mut impl DowngradeContext) -> Result<At
|
||||
.into_iter()
|
||||
.map(|part| match part {
|
||||
Literal(lit) => Ok(ctx.new_expr(self::Str { val: lit, span }.to_ir())),
|
||||
Interpolation(interpol) => interpol.expr().unwrap().downgrade(ctx),
|
||||
Interpolation(interpol) => interpol
|
||||
.expr()
|
||||
.require(ctx, interpol.syntax().text_range())?
|
||||
.downgrade(ctx),
|
||||
})
|
||||
.collect::<Result<Vec<_>>>()?;
|
||||
Ok(Attr::Dynamic(
|
||||
@@ -927,10 +980,13 @@ fn downgrade_attr(attr: ast::Attr, ctx: &mut impl DowngradeContext) -> Result<At
|
||||
))
|
||||
}
|
||||
}
|
||||
Dynamic(dynamic) => Ok(Attr::Dynamic(
|
||||
dynamic.expr().unwrap().downgrade(ctx)?,
|
||||
dynamic.syntax().text_range(),
|
||||
)),
|
||||
Dynamic(dynamic) => {
|
||||
let span = dynamic.syntax().text_range();
|
||||
Ok(Attr::Dynamic(
|
||||
dynamic.expr().require(ctx, span)?.downgrade(ctx)?,
|
||||
span,
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -972,7 +1028,7 @@ where
|
||||
let (params, mut binding_keys) = pat_entries
|
||||
.into_iter()
|
||||
.map(|entry| {
|
||||
let ident = entry.ident().unwrap();
|
||||
let ident = entry.ident().require(ctx, entry.syntax().text_range())?;
|
||||
let sym_span = ident.syntax().text_range();
|
||||
let sym = ctx.new_sym(ident.syntax().text().to_string());
|
||||
let default = entry.default();
|
||||
@@ -1038,7 +1094,7 @@ where
|
||||
span,
|
||||
} in params
|
||||
{
|
||||
let slot = *let_bindings.get(&sym).unwrap();
|
||||
let slot = *let_bindings.get(&sym).expect("binding registered");
|
||||
|
||||
let default = if let Some(default) = default {
|
||||
let default = default.clone().downgrade(ctx)?;
|
||||
@@ -1060,7 +1116,7 @@ where
|
||||
}
|
||||
|
||||
if let Some(alias_sym) = alias {
|
||||
let slot = *let_bindings.get(&alias_sym).unwrap();
|
||||
let slot = *let_bindings.get(&alias_sym).expect("binding registered");
|
||||
ctx.register_thunk(slot, arg);
|
||||
}
|
||||
|
||||
@@ -1318,20 +1374,22 @@ fn downgrade_path(
|
||||
}
|
||||
.to_ir(),
|
||||
)),
|
||||
ast::InterpolPart::Interpolation(interpol) => interpol.expr().unwrap().downgrade(ctx),
|
||||
ast::InterpolPart::Interpolation(interpol) => interpol
|
||||
.expr()
|
||||
.require(ctx, interpol.syntax().text_range())?
|
||||
.downgrade(ctx),
|
||||
})
|
||||
.collect::<Result<Vec<_>>>()?;
|
||||
let expr = if parts.len() == 1 {
|
||||
parts.into_iter().next().unwrap()
|
||||
} else {
|
||||
ctx.new_expr(
|
||||
let expr = match parts.try_conv::<[_; 1]>() {
|
||||
Ok([part]) => part,
|
||||
Err(parts) => ctx.new_expr(
|
||||
ConcatStrings {
|
||||
parts,
|
||||
span,
|
||||
force_string: false,
|
||||
}
|
||||
.to_ir(),
|
||||
)
|
||||
),
|
||||
};
|
||||
Ok(ctx.new_expr(Path { expr, span }.to_ir()))
|
||||
}
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
#![allow(unused_assignments)]
|
||||
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::sync::Arc;
|
||||
|
||||
|
||||
@@ -133,9 +133,7 @@ impl<Ctx: RuntimeContext> Runtime<Ctx> {
|
||||
deno_core::v8_set_flags(vec!["".into(), format!("--stack-size={}", 8 * 1024)]),
|
||||
[""]
|
||||
);
|
||||
JsRuntime::init_platform(
|
||||
Some(v8::new_default_platform(0, false).make_shared()),
|
||||
);
|
||||
JsRuntime::init_platform(Some(v8::new_default_platform(0, false).make_shared()));
|
||||
});
|
||||
|
||||
let mut js_runtime = JsRuntime::new(RuntimeOptions {
|
||||
|
||||
@@ -552,9 +552,13 @@ impl NixDaemonClient {
|
||||
assert_eq!(type_marker, "Error");
|
||||
|
||||
let level = NixDaemonErrorLevel::try_from_primitive(
|
||||
self.reader.read_number().await?.try_into().unwrap(),
|
||||
self.reader
|
||||
.read_number()
|
||||
.await?
|
||||
.try_into()
|
||||
.map_err(|_| IoError::other("invalid nix-daemon error level"))?,
|
||||
)
|
||||
.unwrap();
|
||||
.map_err(|_| IoError::other("invalid nix-daemon error level"))?;
|
||||
// removed
|
||||
let _name: String = self.reader.read_value().await?;
|
||||
let msg: String = self.reader.read_value().await?;
|
||||
|
||||
@@ -206,11 +206,15 @@ eval_okay_test!(
|
||||
eval_okay_test!(partition);
|
||||
eval_okay_test!(path);
|
||||
eval_okay_test!(pathexists);
|
||||
eval_okay_test!(path_string_interpolation, || {
|
||||
unsafe {
|
||||
std::env::set_var("HOME", "/fake-home");
|
||||
eval_okay_test!(
|
||||
#[ignore = "rnix 0.13 regression: /${foo}-/*...*/ fails to parse"]
|
||||
path_string_interpolation,
|
||||
|| {
|
||||
unsafe {
|
||||
std::env::set_var("HOME", "/fake-home");
|
||||
}
|
||||
}
|
||||
});
|
||||
);
|
||||
eval_okay_test!(patterns);
|
||||
eval_okay_test!(print);
|
||||
eval_okay_test!(readDir);
|
||||
|
||||
Reference in New Issue
Block a user