1use std::{collections::HashMap, hash::BuildHasher};23use jrsonnet_gcmodule::Trace;4use jrsonnet_interner::IStr;5use jrsonnet_ir::{SourceFifo, SourcePath};67use crate::{8 function::{CallLocation, PreparedFuncVal},9 in_description_frame, with_state, Result, Thunk, Val,10};1112#[derive(Clone, Trace)]13pub enum TlaArg {14 String(IStr),15 Val(Val),16 Lazy(Thunk<Val>),17 Import(String),18 ImportStr(String),19 InlineCode(String),20}21impl TlaArg {22 pub fn evaluate_tailstrict(&self) -> Result<Val> {23 match self {24 Self::String(s) => Ok(Val::string(s.clone())),25 Self::Val(val) => Ok(val.clone()),26 Self::Lazy(lazy) => Ok(lazy.evaluate()?),27 Self::Import(p) => with_state(|s| {28 let resolved = s.resolve_from_default(&p.as_str())?;29 s.import_resolved(resolved)30 }),31 Self::ImportStr(p) => with_state(|s| {32 let resolved = s.resolve_from_default(&p.as_str())?;33 s.import_resolved_str(resolved).map(Val::string)34 }),35 Self::InlineCode(p) => with_state(|s| {36 let resolved =37 SourcePath::new(SourceFifo("<inline code>".to_owned(), p.as_bytes().into()));38 s.import_resolved(resolved)39 }),40 }41 }42 pub fn evaluate(&self) -> Result<Thunk<Val>> {43 match self {44 Self::String(s) => Ok(Thunk::evaluated(Val::string(s.clone()))),45 Self::Val(val) => Ok(Thunk::evaluated(val.clone())),46 Self::Lazy(lazy) => Ok(lazy.clone()),47 Self::Import(p) => with_state(|s| {48 let resolved = s.resolve_from_default(&p.as_str())?;49 Ok(Thunk!(move || s.import_resolved(resolved)))50 }),51 Self::ImportStr(p) => with_state(|s| {52 let resolved = s.resolve_from_default(&p.as_str())?;53 Ok(Thunk!(move || s54 .import_resolved_str(resolved)55 .map(Val::string)))56 }),57 Self::InlineCode(p) => with_state(|s| {58 let resolved =59 SourcePath::new(SourceFifo("<inline code>".to_owned(), p.as_bytes().into()));60 Ok(Thunk!(move || s.import_resolved(resolved)))61 }),62 }63 }64}6566pub fn apply_tla<H: BuildHasher>(args: &HashMap<IStr, TlaArg, H>, val: Val) -> Result<Val> {67 Ok(if let Val::Func(func) = val {68 in_description_frame(69 || "during TLA call".to_owned(),70 || {71 let mut names = Vec::with_capacity(args.len());72 let mut values = Vec::with_capacity(args.len());73 for (name, value) in args {74 names.push(name.clone());75 values.push(value.evaluate()?);76 }77 let prepared = PreparedFuncVal::new(func, 0, &names)?;78 prepared.call(CallLocation::native(), &[], &values)79 },80 )?81 } else {82 val83 })84}