From dde7edac36b00bbbba0e305e48d060323136585e Mon Sep 17 00:00:00 2001 From: Yaroslav Bolyukin Date: Sat, 23 Jul 2022 22:26:30 +0000 Subject: [PATCH] refactor(cli): move to split stdlib --- --- a/cmds/jrsonnet/Cargo.toml +++ b/cmds/jrsonnet/Cargo.toml @@ -15,6 +15,7 @@ "jrsonnet-evaluator/exp-preserve-order", "jrsonnet-evaluator/exp-serde-preserve-order", "jrsonnet-cli/exp-preserve-order", + "jrsonnet-cli/exp-serde-preserve-order", ] # Destructuring of locals exp-destruct = ["jrsonnet-evaluator/exp-destruct"] @@ -27,5 +28,5 @@ mimallocator = { version = "0.1.3", optional = true } thiserror = "1.0" -clap = { version = "3.1", features = ["derive"] } -clap_complete = { version = "3.1" } +clap = { version = "3.2", features = ["derive"] } +clap_complete = { version = "3.2" } --- a/crates/jrsonnet-cli/Cargo.toml +++ b/crates/jrsonnet-cli/Cargo.toml @@ -7,7 +7,14 @@ edition = "2021" [features] -exp-preserve-order = ["jrsonnet-evaluator/exp-preserve-order"] +exp-preserve-order = [ + "jrsonnet-evaluator/exp-preserve-order", + "jrsonnet-stdlib/exp-preserve-order", +] +exp-serde-preserve-order = [ + "jrsonnet-evaluator/exp-serde-preserve-order", + "jrsonnet-stdlib/exp-serde-preserve-order", +] [dependencies] jrsonnet-evaluator = { path = "../../crates/jrsonnet-evaluator", version = "0.4.2", features = [ @@ -15,5 +22,6 @@ ] } jrsonnet-parser = { path = "../../crates/jrsonnet-parser", version = "0.4.2" } jrsonnet-gcmodule = { version = "0.3.4" } +jrsonnet-stdlib = { path = "../../crates/jrsonnet-stdlib", version = "0.4.2" } -clap = { version = "3.1", features = ["derive"] } +clap = { version = "3.2", features = ["derive"] } --- a/crates/jrsonnet-cli/src/ext.rs +++ /dev/null @@ -1,118 +0,0 @@ -use std::{fs::read_to_string, str::FromStr}; - -use clap::Parser; -use jrsonnet_evaluator::{error::Result, State}; - -use crate::ConfigureState; - -#[derive(Clone)] -pub struct ExtStr { - pub name: String, - pub value: String, -} - -impl FromStr for ExtStr { - type Err = &'static str; - fn from_str(s: &str) -> std::result::Result { - let out: Vec<_> = s.split('=').collect(); - match out.len() { - 1 => Ok(ExtStr { - name: out[0].to_owned(), - value: std::env::var(out[0]).or(Err("missing env var"))?, - }), - 2 => Ok(ExtStr { - name: out[0].to_owned(), - value: out[1].to_owned(), - }), - - _ => Err("bad ext-str syntax"), - } - } -} - -#[derive(Clone)] -pub struct ExtFile { - pub name: String, - pub value: String, -} - -impl FromStr for ExtFile { - type Err = String; - - fn from_str(s: &str) -> std::result::Result { - let out: Vec<&str> = s.split('=').collect(); - if out.len() != 2 { - return Err("bad ext-file syntax".to_owned()); - } - let file = read_to_string(&out[1]); - match file { - Ok(content) => Ok(Self { - name: out[0].into(), - value: content, - }), - Err(e) => Err(format!("{}", e)), - } - } -} - -#[derive(Parser)] -#[clap(next_help_heading = "EXTERNAL VARIABLES")] -pub struct ExtVarOpts { - /// Add string external variable. - /// External variables are globally available so it is preferred - /// to use top level arguments whenever it's possible. - /// If [=data] is not set then it will be read from `name` env variable. - /// Can be accessed from code via `std.extVar("name")`. - #[clap( - long, - short = 'V', - name = "name[=var data]", - number_of_values = 1, - multiple_occurrences = true - )] - ext_str: Vec, - /// Read string external variable from file. - /// See also `--ext-str` - #[clap( - long, - name = "name=var path", - number_of_values = 1, - multiple_occurrences = true - )] - ext_str_file: Vec, - /// Add external variable from code. - /// See also `--ext-str` - #[clap( - long, - name = "name[=var source]", - number_of_values = 1, - multiple_occurrences = true - )] - ext_code: Vec, - /// Read string external variable from file. - /// See also `--ext-str` - #[clap( - long, - name = "name=var code path", - number_of_values = 1, - multiple_occurrences = true - )] - ext_code_file: Vec, -} -impl ConfigureState for ExtVarOpts { - fn configure(&self, s: &State) -> Result<()> { - for ext in self.ext_str.iter() { - s.add_ext_str((&ext.name as &str).into(), (&ext.value as &str).into()); - } - for ext in self.ext_str_file.iter() { - s.add_ext_str((&ext.name as &str).into(), (&ext.value as &str).into()); - } - for ext in self.ext_code.iter() { - s.add_ext_code(&ext.name as &str, (&ext.value as &str).into())?; - } - for ext in self.ext_code_file.iter() { - s.add_ext_code(&ext.name as &str, (&ext.value as &str).into())?; - } - Ok(()) - } -} --- a/crates/jrsonnet-cli/src/lib.rs +++ b/crates/jrsonnet-cli/src/lib.rs @@ -1,15 +1,15 @@ -mod ext; mod manifest; +mod stdlib; mod tla; mod trace; use std::{env, path::PathBuf}; use clap::Parser; -pub use ext::*; use jrsonnet_evaluator::{error::Result, FileImportResolver, State}; use jrsonnet_gcmodule::with_thread_object_space; pub use manifest::*; +pub use stdlib::*; pub use tla::*; pub use trace::*; @@ -31,13 +31,6 @@ #[derive(Parser)] #[clap(next_help_heading = "OPTIONS")] pub struct MiscOpts { - /// Disable standard library. - /// By default standard library will be available via global `std` variable. - /// Note that standard library will still be loaded - /// if chosen manifestification method is not `none`. - #[clap(long)] - no_stdlib: bool, - /// Maximal allowed number of stack frames, /// stack overflow error will be raised if this number gets exceeded. #[clap(long, short = 's', default_value = "200")] @@ -52,10 +45,6 @@ } impl ConfigureState for MiscOpts { fn configure(&self, s: &State) -> Result<()> { - if !self.no_stdlib { - s.with_stdlib(); - } - let mut library_paths = self.jpath.clone(); library_paths.reverse(); if let Some(path) = env::var_os("JSONNET_PATH") { @@ -79,7 +68,7 @@ #[clap(flatten)] tla: TLAOpts, #[clap(flatten)] - ext: ExtVarOpts, + std: StdOpts, #[clap(flatten)] trace: TraceOpts, @@ -91,7 +80,7 @@ self.trace.configure(s)?; self.misc.configure(s)?; self.tla.configure(s)?; - self.ext.configure(s)?; + self.std.configure(s)?; Ok(()) } } @@ -114,10 +103,10 @@ impl GcOpts { pub fn stats_printer(&self) -> (Option, Option) { ( - self.gc_print_stats.then(|| GcStatsPrinter { + self.gc_print_stats.then_some(GcStatsPrinter { collect_before_printing_stats: self.gc_collect_before_printing_stats, }), - (!self.gc_collect_on_exit).then(|| LeakSpace {}), + (!self.gc_collect_on_exit).then_some(LeakSpace {}), ) } } --- /dev/null +++ b/crates/jrsonnet-cli/src/stdlib.rs @@ -0,0 +1,129 @@ +use std::{fs::read_to_string, str::FromStr}; + +use clap::Parser; +use jrsonnet_evaluator::{error::Result, State}; + +use crate::ConfigureState; + +#[derive(Clone)] +pub struct ExtStr { + pub name: String, + pub value: String, +} + +impl FromStr for ExtStr { + type Err = &'static str; + fn from_str(s: &str) -> std::result::Result { + let out: Vec<_> = s.split('=').collect(); + match out.len() { + 1 => Ok(ExtStr { + name: out[0].to_owned(), + value: std::env::var(out[0]).or(Err("missing env var"))?, + }), + 2 => Ok(ExtStr { + name: out[0].to_owned(), + value: out[1].to_owned(), + }), + + _ => Err("bad ext-str syntax"), + } + } +} + +#[derive(Clone)] +pub struct ExtFile { + pub name: String, + pub value: String, +} + +impl FromStr for ExtFile { + type Err = String; + + fn from_str(s: &str) -> std::result::Result { + let out: Vec<&str> = s.split('=').collect(); + if out.len() != 2 { + return Err("bad ext-file syntax".to_owned()); + } + let file = read_to_string(&out[1]); + match file { + Ok(content) => Ok(Self { + name: out[0].into(), + value: content, + }), + Err(e) => Err(format!("{}", e)), + } + } +} + +#[derive(Parser)] +#[clap(next_help_heading = "STANDARD LIBRARY")] +pub struct StdOpts { + /// Disable standard library. + /// By default standard library will be available via global `std` variable. + /// Note that standard library will still be loaded + /// if chosen manifestification method is not `none`. + #[clap(long)] + no_stdlib: bool, + /// Add string external variable. + /// External variables are globally available so it is preferred + /// to use top level arguments whenever it's possible. + /// If [=data] is not set then it will be read from `name` env variable. + /// Can be accessed from code via `std.extVar("name")`. + #[clap( + long, + short = 'V', + name = "name[=var data]", + number_of_values = 1, + multiple_occurrences = true + )] + ext_str: Vec, + /// Read string external variable from file. + /// See also `--ext-str` + #[clap( + long, + name = "name=var path", + number_of_values = 1, + multiple_occurrences = true + )] + ext_str_file: Vec, + /// Add external variable from code. + /// See also `--ext-str` + #[clap( + long, + name = "name[=var source]", + number_of_values = 1, + multiple_occurrences = true + )] + ext_code: Vec, + /// Read string external variable from file. + /// See also `--ext-str` + #[clap( + long, + name = "name=var code path", + number_of_values = 1, + multiple_occurrences = true + )] + ext_code_file: Vec, +} +impl ConfigureState for StdOpts { + fn configure(&self, s: &State) -> Result<()> { + if self.no_stdlib { + return Ok(()); + } + let ctx = jrsonnet_stdlib::ContextInitializer::new(s.clone()); + for ext in self.ext_str.iter() { + ctx.add_ext_str((&ext.name as &str).into(), (&ext.value as &str).into()); + } + for ext in self.ext_str_file.iter() { + ctx.add_ext_str((&ext.name as &str).into(), (&ext.value as &str).into()); + } + for ext in self.ext_code.iter() { + ctx.add_ext_code(&ext.name as &str, (&ext.value as &str).into())?; + } + for ext in self.ext_code_file.iter() { + ctx.add_ext_code(&ext.name as &str, (&ext.value as &str).into())?; + } + s.settings_mut().context_initializer = Box::new(ctx); + Ok(()) + } +} -- gitstuff