git.delta.rocks / jrsonnet / refs/commits / 4cba987da17b

difftreelog

fix parser imports after renaming

Лач2020-06-27parent: #b9714ab.patch.diff
in: master

1 file changed

modifiedcmds/jrsonnet/src/main.rsdiffbeforeafterboth
before · cmds/jrsonnet/src/main.rs
1pub 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}
after · cmds/jrsonnet/src/main.rs
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}