difftreelog
fix parser imports after renaming
in: master
1 file changed
cmds/jrsonnet/src/main.rsdiffbeforeafterboth1pub mod location;23use clap::Clap;4use jrsonnet_evaluator::{EvaluationSettings, EvaluationState, LocError, StackTrace, Val};5use jsonnet_parser::{el, Arg, ArgsDesc, Expr, LocExpr, ParserSettings};6use location::{offset_to_location, CodeLocation};7use std::env::current_dir;8use std::{collections::HashMap, path::PathBuf, rc::Rc, str::FromStr};910#[global_allocator]11static ALLOC: jemallocator::Jemalloc = jemallocator::Jemalloc;1213enum Format {14 None,15 Json,16 Yaml,17}1819impl FromStr for Format {20 type Err = &'static str;21 fn from_str(s: &str) -> Result<Self, Self::Err> {22 Ok(match s {23 "none" => Format::None,24 "json" => Format::Json,25 "yaml" => Format::Yaml,26 _ => return Err("no such format"),27 })28 }29}3031#[derive(PartialEq)]32enum TraceFormat {33 CppJsonnet,34 GoJsonnet,35 Custom,36}37impl FromStr for TraceFormat {38 type Err = &'static str;39 fn from_str(s: &str) -> Result<Self, Self::Err> {40 Ok(match s {41 "cpp" => TraceFormat::CppJsonnet,42 "go" => TraceFormat::GoJsonnet,43 "default" => TraceFormat::Custom,44 _ => return Err("no such format"),45 })46 }47}4849#[derive(Clone)]50struct ExtStr {51 name: String,52 value: String,53}54impl FromStr for ExtStr {55 type Err = &'static str;56 fn from_str(s: &str) -> Result<Self, Self::Err> {57 let out: Vec<_> = s.split('=').collect();58 match out.len() {59 1 => Ok(ExtStr {60 name: out[0].to_owned(),61 value: std::env::var(out[0]).or(Err("missing env var"))?,62 }),63 2 => Ok(ExtStr {64 name: out[0].to_owned(),65 value: out[1].to_owned(),66 }),67 _ => Err("bad ext-str syntax"),68 }69 }70}7172#[derive(Clap)]73#[clap(version = "0.1.0", author = "Lach <iam@lach.pw>")]74struct Opts {75 #[clap(long, about = "Disable global std variable")]76 no_stdlib: bool,77 #[clap(long, about = "Add external string")]78 ext_str: Vec<ExtStr>,79 #[clap(long, about = "Add external string from code")]80 ext_code: Vec<ExtStr>,81 #[clap(long, about = "Add TLA")]82 tla_str: Vec<ExtStr>,83 #[clap(long, about = "Add TLA from code")]84 tla_code: Vec<ExtStr>,85 #[clap(long, short = "f", default_value = "json", possible_values = &["none", "json", "yaml"], about = "Output format, wraps resulting value to corresponding std.manifest call")]86 format: Format,87 #[clap(long, default_value = "default", possible_values = &["cpp", "go", "default"], about = "Emulated needed stacktrace display")]88 trace_format: TraceFormat,8990 #[clap(91 long,92 short = "s",93 default_value = "200",94 about = "Number of allowed stack frames"95 )]96 max_stack: usize,97 #[clap(98 long,99 short = "t",100 default_value = "20",101 about = "Max length of stack trace before cropping"102 )]103 max_trace: usize,104105 #[clap(long, short = "J", about = "Library search dir")]106 jpath: Vec<PathBuf>,107108 #[clap(109 long,110 default_value = "3",111 about = "When using --format, this option specifies string to pad output with"112 )]113 line_padding: usize,114115 #[clap(about = "File to compile", index = 1)]116 input: String,117}118119fn main() {120 let opts: Opts = Opts::parse();121 let evaluator = jrsonnet_evaluator::EvaluationState::new(122 EvaluationSettings {123 max_stack_trace_size: opts.max_trace,124 max_stack_frames: opts.max_stack,125 },126 Box::new(jrsonnet_evaluator::FileImportResolver {127 library_paths: opts.jpath.clone(),128 }),129 );130 if !opts.no_stdlib {131 evaluator.with_stdlib();132 }133 for ExtStr { name, value } in opts.ext_str.iter().cloned() {134 evaluator.add_ext_var(name.into(), Val::Str(value.into()));135 }136 for ExtStr { name, value } in opts.ext_code.iter().cloned() {137 evaluator.add_ext_var(name.into(), evaluator.parse_evaluate_raw(&value).unwrap());138 }139 let mut input = current_dir().unwrap();140 input.push(opts.input.clone());141 let code_string = String::from_utf8(std::fs::read(opts.input.clone()).unwrap()).unwrap();142 if let Err(e) = evaluator.add_file(Rc::new(input.clone()), code_string.clone().into()) {143 print_syntax_error(e, &input, &code_string);144 std::process::exit(1);145 }146 let result = evaluator.evaluate_file(&input);147 match result {148 Ok(v) => {149 let v = match v {150 Val::Func(f) => {151 let mut desc_map = HashMap::new();152 for ExtStr { name, value } in opts.tla_str.iter().cloned() {153 desc_map.insert(name, el!(Expr::Str(value.into())));154 }155 for ExtStr { name, value } in opts.tla_code.iter().cloned() {156 desc_map.insert(157 name,158 jsonnet_parser::parse(159 &value,160 &ParserSettings {161 file_name: Rc::new(PathBuf::new()),162 loc_data: false,163 },164 )165 .unwrap(),166 );167 }168 evaluator.add_global("__tmp__tlf__".into(), Val::Func(f));169 evaluator170 .evaluate_raw(el!(Expr::Apply(171 el!(Expr::Var("__tmp__tlf__".into())),172 ArgsDesc(desc_map.into_iter().map(|(k, v)| Arg(Some(k), v)).collect()),173 false,174 )))175 .unwrap()176 }177 v => v,178 };179 let v = evaluator.run_in_state(|| match opts.format {180 Format::Json => Ok(Val::Str(v.into_json(opts.line_padding)?)),181 Format::Yaml => {182 evaluator.add_global("__tmp__to_yaml__".into(), v);183 evaluator.parse_evaluate_raw("std.manifestYamlDoc(__tmp__to_yaml__, \" \")")184 }185 _ => Ok(v),186 });187 let v = match v {188 Ok(v) => v,189 Err(err) => {190 print_error(&err, evaluator, &opts);191 std::process::exit(1);192 }193 };194 match v {195 Val::Str(s) => println!("{}", s),196 Val::Num(n) => println!("{}", n),197 _v => eprintln!(198 "jsonnet output is not a string.\nDid you forgot to set --format, or wrap your data with std.manifestJson?"199 ),200 }201 }202 Err(err) => {203 print_error(&err, evaluator, &opts);204 std::process::exit(1);205 }206 }207}208209fn print_error(err: &LocError, evaluator: EvaluationState, opts: &Opts) {210 println!("Error: {:?}", err.0);211 print_trace(&(err.1), evaluator, &opts);212}213214fn print_syntax_error(error: jsonnet_parser::ParseError, file: &PathBuf, code: &str) {215 use annotate_snippets::{216 display_list::{DisplayList, FormatOptions},217 snippet::{Annotation, AnnotationType, Slice, Snippet, SourceAnnotation},218 };219 //&("Expected: ".to_owned() + error.expected)220 let origin = file.to_str().unwrap();221 let error_message = format!("Expected: {}", error.expected);222 let snippet = Snippet {223 opt: FormatOptions {224 color: true,225 ..Default::default()226 },227 title: Some(Annotation {228 label: Some(&error_message),229 id: None,230 annotation_type: AnnotationType::Error,231 }),232 footer: vec![],233 slices: vec![Slice {234 source: &code,235 line_start: 1,236 origin: Some(origin),237 fold: false,238 annotations: vec![SourceAnnotation {239 label: "At this position",240 annotation_type: AnnotationType::Error,241 range: (error.location.offset, error.location.offset + 1),242 }],243 }],244 };245246 let dl = DisplayList::from(snippet);247 println!("{}", dl);248}249250fn print_trace(trace: &StackTrace, evaluator: EvaluationState, opts: &Opts) {251 use annotate_snippets::{252 display_list::{DisplayList, FormatOptions},253 snippet::{Annotation, AnnotationType, Slice, Snippet, SourceAnnotation},254 };255 for item in trace.0.iter() {256 let desc = &item.1;257 let source = item.0.clone();258 let code = evaluator.get_source(&source.0);259 if code.is_none() {260 continue;261 }262 let code = code.unwrap();263 let start_end = offset_to_location(&code, &[source.1, source.2]);264 if opts.trace_format == TraceFormat::Custom {265 let source_fragment: String = code266 .chars()267 .skip(start_end[0].line_start_offset)268 .take(start_end[1].line_end_offset - start_end[0].line_start_offset)269 .collect();270 let snippet = Snippet {271 opt: FormatOptions {272 color: true,273 ..Default::default()274 },275 title: Some(Annotation {276 label: Some(&item.1),277 id: None,278 annotation_type: AnnotationType::Error,279 }),280 footer: vec![],281 slices: vec![Slice {282 source: &source_fragment,283 line_start: start_end[0].line,284 origin: Some(&source.0.to_str().unwrap()),285 fold: false,286 annotations: vec![SourceAnnotation {287 label: desc,288 annotation_type: AnnotationType::Error,289 range: (290 source.1 - start_end[0].line_start_offset,291 source.2 - start_end[0].line_start_offset,292 ),293 }],294 }],295 };296297 let dl = DisplayList::from(snippet);298 println!("{}", dl);299 } else {300 print_jsonnet_pair(301 source.0.to_str().unwrap(),302 &start_end[0],303 &start_end[1],304 opts.trace_format == TraceFormat::GoJsonnet,305 );306 }307 }308}309310fn print_jsonnet_pair(file: &str, start: &CodeLocation, end: &CodeLocation, is_go: bool) {311 if is_go {312 print!(" ");313 } else {314 print!(" ");315 }316 print!("{}:", file);317 if start.line == end.line {318 // IDK why, but this is the behavior original jsonnet cpp impl shows319 if start.column == end.column || !is_go && start.column + 1 == end.column {320 println!("{}:{}", start.line, end.column)321 } else {322 println!("{}:{}-{}", start.line, start.column, end.column);323 }324 } else {325 println!(326 "({}:{})-({}:{})",327 start.line, end.column, start.line, end.column328 );329 }330}1pub mod location;23use clap::Clap;4use jrsonnet_evaluator::{EvaluationSettings, EvaluationState, LocError, StackTrace, Val};5use jrsonnet_parser::{el, Arg, ArgsDesc, Expr, LocExpr, ParserSettings};6use location::{offset_to_location, CodeLocation};7use std::env::current_dir;8use std::{collections::HashMap, path::PathBuf, rc::Rc, str::FromStr};910#[global_allocator]11static ALLOC: jemallocator::Jemalloc = jemallocator::Jemalloc;1213enum Format {14 None,15 Json,16 Yaml,17}1819impl FromStr for Format {20 type Err = &'static str;21 fn from_str(s: &str) -> Result<Self, Self::Err> {22 Ok(match s {23 "none" => Format::None,24 "json" => Format::Json,25 "yaml" => Format::Yaml,26 _ => return Err("no such format"),27 })28 }29}3031#[derive(PartialEq)]32enum TraceFormat {33 CppJsonnet,34 GoJsonnet,35 Custom,36}37impl FromStr for TraceFormat {38 type Err = &'static str;39 fn from_str(s: &str) -> Result<Self, Self::Err> {40 Ok(match s {41 "cpp" => TraceFormat::CppJsonnet,42 "go" => TraceFormat::GoJsonnet,43 "default" => TraceFormat::Custom,44 _ => return Err("no such format"),45 })46 }47}4849#[derive(Clone)]50struct ExtStr {51 name: String,52 value: String,53}54impl FromStr for ExtStr {55 type Err = &'static str;56 fn from_str(s: &str) -> Result<Self, Self::Err> {57 let out: Vec<_> = s.split('=').collect();58 match out.len() {59 1 => Ok(ExtStr {60 name: out[0].to_owned(),61 value: std::env::var(out[0]).or(Err("missing env var"))?,62 }),63 2 => Ok(ExtStr {64 name: out[0].to_owned(),65 value: out[1].to_owned(),66 }),67 _ => Err("bad ext-str syntax"),68 }69 }70}7172#[derive(Clap)]73#[clap(version = "0.1.0", author = "Lach <iam@lach.pw>")]74struct Opts {75 #[clap(long, about = "Disable global std variable")]76 no_stdlib: bool,77 #[clap(long, about = "Add external string")]78 ext_str: Vec<ExtStr>,79 #[clap(long, about = "Add external string from code")]80 ext_code: Vec<ExtStr>,81 #[clap(long, about = "Add TLA")]82 tla_str: Vec<ExtStr>,83 #[clap(long, about = "Add TLA from code")]84 tla_code: Vec<ExtStr>,85 #[clap(long, short = "f", default_value = "json", possible_values = &["none", "json", "yaml"], about = "Output format, wraps resulting value to corresponding std.manifest call")]86 format: Format,87 #[clap(long, default_value = "default", possible_values = &["cpp", "go", "default"], about = "Emulated needed stacktrace display")]88 trace_format: TraceFormat,8990 #[clap(91 long,92 short = "s",93 default_value = "200",94 about = "Number of allowed stack frames"95 )]96 max_stack: usize,97 #[clap(98 long,99 short = "t",100 default_value = "20",101 about = "Max length of stack trace before cropping"102 )]103 max_trace: usize,104105 #[clap(long, short = "J", about = "Library search dir")]106 jpath: Vec<PathBuf>,107108 #[clap(109 long,110 default_value = "3",111 about = "When using --format, this option specifies string to pad output with"112 )]113 line_padding: usize,114115 #[clap(about = "File to compile", index = 1)]116 input: String,117}118119fn main() {120 let opts: Opts = Opts::parse();121 let evaluator = jrsonnet_evaluator::EvaluationState::new(122 EvaluationSettings {123 max_stack_trace_size: opts.max_trace,124 max_stack_frames: opts.max_stack,125 },126 Box::new(jrsonnet_evaluator::FileImportResolver {127 library_paths: opts.jpath.clone(),128 }),129 );130 if !opts.no_stdlib {131 evaluator.with_stdlib();132 }133 for ExtStr { name, value } in opts.ext_str.iter().cloned() {134 evaluator.add_ext_var(name.into(), Val::Str(value.into()));135 }136 for ExtStr { name, value } in opts.ext_code.iter().cloned() {137 evaluator.add_ext_var(name.into(), evaluator.parse_evaluate_raw(&value).unwrap());138 }139 let mut input = current_dir().unwrap();140 input.push(opts.input.clone());141 let code_string = String::from_utf8(std::fs::read(opts.input.clone()).unwrap()).unwrap();142 if let Err(e) = evaluator.add_file(Rc::new(input.clone()), code_string.clone().into()) {143 print_syntax_error(e, &input, &code_string);144 std::process::exit(1);145 }146 let result = evaluator.evaluate_file(&input);147 match result {148 Ok(v) => {149 let v = match v {150 Val::Func(f) => {151 let mut desc_map = HashMap::new();152 for ExtStr { name, value } in opts.tla_str.iter().cloned() {153 desc_map.insert(name, el!(Expr::Str(value.into())));154 }155 for ExtStr { name, value } in opts.tla_code.iter().cloned() {156 desc_map.insert(157 name,158 jrsonnet_parser::parse(159 &value,160 &ParserSettings {161 file_name: Rc::new(PathBuf::new()),162 loc_data: false,163 },164 )165 .unwrap(),166 );167 }168 evaluator.add_global("__tmp__tlf__".into(), Val::Func(f));169 evaluator170 .evaluate_raw(el!(Expr::Apply(171 el!(Expr::Var("__tmp__tlf__".into())),172 ArgsDesc(desc_map.into_iter().map(|(k, v)| Arg(Some(k), v)).collect()),173 false,174 )))175 .unwrap()176 }177 v => v,178 };179 let v = evaluator.run_in_state(|| match opts.format {180 Format::Json => Ok(Val::Str(v.into_json(opts.line_padding)?)),181 Format::Yaml => {182 evaluator.add_global("__tmp__to_yaml__".into(), v);183 evaluator.parse_evaluate_raw("std.manifestYamlDoc(__tmp__to_yaml__, \" \")")184 }185 _ => Ok(v),186 });187 let v = match v {188 Ok(v) => v,189 Err(err) => {190 print_error(&err, evaluator, &opts);191 std::process::exit(1);192 }193 };194 match v {195 Val::Str(s) => println!("{}", s),196 Val::Num(n) => println!("{}", n),197 _v => eprintln!(198 "jsonnet output is not a string.\nDid you forgot to set --format, or wrap your data with std.manifestJson?"199 ),200 }201 }202 Err(err) => {203 print_error(&err, evaluator, &opts);204 std::process::exit(1);205 }206 }207}208209fn print_error(err: &LocError, evaluator: EvaluationState, opts: &Opts) {210 println!("Error: {:?}", err.0);211 print_trace(&(err.1), evaluator, &opts);212}213214fn print_syntax_error(error: jrsonnet_parser::ParseError, file: &PathBuf, code: &str) {215 use annotate_snippets::{216 display_list::{DisplayList, FormatOptions},217 snippet::{Annotation, AnnotationType, Slice, Snippet, SourceAnnotation},218 };219 //&("Expected: ".to_owned() + error.expected)220 let origin = file.to_str().unwrap();221 let error_message = format!("Expected: {}", error.expected);222 let snippet = Snippet {223 opt: FormatOptions {224 color: true,225 ..Default::default()226 },227 title: Some(Annotation {228 label: Some(&error_message),229 id: None,230 annotation_type: AnnotationType::Error,231 }),232 footer: vec![],233 slices: vec![Slice {234 source: &code,235 line_start: 1,236 origin: Some(origin),237 fold: false,238 annotations: vec![SourceAnnotation {239 label: "At this position",240 annotation_type: AnnotationType::Error,241 range: (error.location.offset, error.location.offset + 1),242 }],243 }],244 };245246 let dl = DisplayList::from(snippet);247 println!("{}", dl);248}249250fn print_trace(trace: &StackTrace, evaluator: EvaluationState, opts: &Opts) {251 use annotate_snippets::{252 display_list::{DisplayList, FormatOptions},253 snippet::{Annotation, AnnotationType, Slice, Snippet, SourceAnnotation},254 };255 for item in trace.0.iter() {256 let desc = &item.1;257 let source = item.0.clone();258 let code = evaluator.get_source(&source.0);259 if code.is_none() {260 continue;261 }262 let code = code.unwrap();263 let start_end = offset_to_location(&code, &[source.1, source.2]);264 if opts.trace_format == TraceFormat::Custom {265 let source_fragment: String = code266 .chars()267 .skip(start_end[0].line_start_offset)268 .take(start_end[1].line_end_offset - start_end[0].line_start_offset)269 .collect();270 let snippet = Snippet {271 opt: FormatOptions {272 color: true,273 ..Default::default()274 },275 title: Some(Annotation {276 label: Some(&item.1),277 id: None,278 annotation_type: AnnotationType::Error,279 }),280 footer: vec![],281 slices: vec![Slice {282 source: &source_fragment,283 line_start: start_end[0].line,284 origin: Some(&source.0.to_str().unwrap()),285 fold: false,286 annotations: vec![SourceAnnotation {287 label: desc,288 annotation_type: AnnotationType::Error,289 range: (290 source.1 - start_end[0].line_start_offset,291 source.2 - start_end[0].line_start_offset,292 ),293 }],294 }],295 };296297 let dl = DisplayList::from(snippet);298 println!("{}", dl);299 } else {300 print_jsonnet_pair(301 source.0.to_str().unwrap(),302 &start_end[0],303 &start_end[1],304 opts.trace_format == TraceFormat::GoJsonnet,305 );306 }307 }308}309310fn print_jsonnet_pair(file: &str, start: &CodeLocation, end: &CodeLocation, is_go: bool) {311 if is_go {312 print!(" ");313 } else {314 print!(" ");315 }316 print!("{}:", file);317 if start.line == end.line {318 // IDK why, but this is the behavior original jsonnet cpp impl shows319 if start.column == end.column || !is_go && start.column + 1 == end.column {320 println!("{}:{}", start.line, end.column)321 } else {322 println!("{}:{}-{}", start.line, start.column, end.column);323 }324 } else {325 println!(326 "({}:{})-({}:{})",327 start.line, end.column, start.line, end.column328 );329 }330}