git.delta.rocks / jrsonnet / refs/commits / 393dcbd419fd

difftreelog

feat(macro) pass call location to builtins

Yaroslav Bolyukin2021-12-26parent: #a5471f2.patch.diff
in: master

8 files changed

addedcmds/jrsonnet-fmt/Cargo.tomldiffbeforeafterboth
--- /dev/null
+++ b/cmds/jrsonnet-fmt/Cargo.toml
@@ -0,0 +1,8 @@
+[package]
+name = "jrsonnet-fmt"
+version = "0.1.0"
+edition = "2021"
+
+[dependencies]
+dprint-core = "0.47.1"
+jrsonnet-parser = { path = "../../crates/jrsonnet-parser" }
addedcmds/jrsonnet-fmt/src/main.rsdiffbeforeafterboth

no changes

modifiedcrates/jrsonnet-evaluator/src/builtin/mod.rsdiffbeforeafterboth
--- a/crates/jrsonnet-evaluator/src/builtin/mod.rs
+++ b/crates/jrsonnet-evaluator/src/builtin/mod.rs
@@ -5,14 +5,13 @@
 	equals,
 	error::{Error::*, Result},
 	operator::evaluate_mod_op,
-	parse_args, primitive_equals, push_frame, throw, with_state, ArrValue, Context, FuncVal,
+	primitive_equals, push_frame, throw, with_state, ArrValue, Context, FuncVal,
 	IndexableVal, Val,
 };
 use format::{format_arr, format_obj};
 use gcmodule::Cc;
 use jrsonnet_interner::IStr;
 use jrsonnet_parser::{ArgsDesc, ExprLocation};
-use jrsonnet_types::ty;
 use serde::Deserialize;
 use serde_yaml::DeserializingQuirks;
 use std::{
@@ -466,19 +465,19 @@
 	Ok(format!("{:x}", md5::compute(&str.as_bytes())))
 }
 
-fn builtin_trace(context: Context, loc: &ExprLocation, args: &ArgsDesc) -> Result<Val> {
-	parse_args!(context, "trace", args, 2, [
-		0, str: ty!(string) => Val::Str;
-		1, rest: ty!(any);
-	], {
-		eprint!("TRACE:");
-			with_state(|s|{
-				let locs = s.map_source_locations(&loc.0, &[loc.1]);
-				eprint!(" {}:{}", loc.0.file_name().unwrap().to_str().unwrap(), locs[0].line);
-			});
-		eprintln!(" {}", str);
-		Ok(rest)
-	})
+#[jrsonnet_macros::builtin]
+fn builtin_trace(#[location] loc: &ExprLocation, str: IStr, rest: Any) -> Result<Any> {
+	eprint!("TRACE:");
+	with_state(|s| {
+		let locs = s.map_source_locations(&loc.0, &[loc.1]);
+		eprint!(
+			" {}:{}",
+			loc.0.file_name().unwrap().to_str().unwrap(),
+			locs[0].line
+		);
+	});
+	eprintln!(" {}", str);
+	Ok(rest) as Result<Any>
 }
 
 #[jrsonnet_macros::builtin]
modifiedcrates/jrsonnet-evaluator/src/error.rsdiffbeforeafterboth
--- a/crates/jrsonnet-evaluator/src/error.rs
+++ b/crates/jrsonnet-evaluator/src/error.rs
@@ -16,8 +16,6 @@
 pub enum Error {
 	#[error("intrinsic not found: {0}")]
 	IntrinsicNotFound(IStr),
-	#[error("argument reordering in intrisics not supported yet")]
-	IntrinsicArgumentReorderingIsNotSupportedYet,
 
 	#[error("operator {0} does not operate on type {1}")]
 	UnaryOperatorDoesNotOperateOnType(UnaryOpType, ValType),
modifiedcrates/jrsonnet-evaluator/src/function.rsdiffbeforeafterboth
--- a/crates/jrsonnet-evaluator/src/function.rs
+++ b/crates/jrsonnet-evaluator/src/function.rs
@@ -311,45 +311,3 @@
 
 	Ok(body_ctx.extend(out, None, None, None))
 }
-
-#[macro_export]
-macro_rules! parse_args {
-	($ctx: expr, $fn_name: expr, $args: expr, $total_args: expr, [
-		$($id: expr, $name: ident: $ty: expr $(=>$match: path)?);+ $(;)?
-	], $handler:block) => {{
-		use $crate::{error::Error::*, throw, evaluate, push_description_frame, typed::CheckType};
-
-		let args = $args;
-		if args.unnamed.len() + args.named.len() > $total_args {
-			throw!(TooManyArgsFunctionHas($total_args));
-		}
-		$(
-			if args.unnamed.len() + args.named.len() <= $id {
-				throw!(FunctionParameterNotBoundInCall(stringify!($name).into()));
-			}
-			// Is named
-			let $name = if $id >= $args.unnamed.len() {
-				let named = &args.named[$id - $args.unnamed.len()];
-				if &named.0 != stringify!($name) {
-					throw!(IntrinsicArgumentReorderingIsNotSupportedYet);
-				}
-				&named.1
-			} else {
-				&$args.unnamed[$id]
-			};
-			let $name = push_description_frame(|| format!("evaluating builtin argument {}", stringify!($name)), || {
-				let value = evaluate($ctx.clone(), &$name)?;
-				$ty.check(&value)?;
-				Ok(value)
-			})?;
-			$(
-				let $name = if let $match(v) = $name {
-					v
-				} else {
-					unreachable!();
-				};
-			)?
-		)+
-		($handler as crate::Result<_>)
-	}};
-}
modifiedcrates/jrsonnet-macros/src/lib.rsdiffbeforeafterboth
--- a/crates/jrsonnet-macros/src/lib.rs
+++ b/crates/jrsonnet-macros/src/lib.rs
@@ -1,6 +1,10 @@
 use proc_macro2::Span;
 use quote::quote;
-use syn::{parse_macro_input, FnArg, Ident, ItemFn, Pat};
+use syn::{parse_macro_input, FnArg, Ident, ItemFn, Pat, PatType};
+
+fn is_location_arg(t: &PatType) -> bool {
+	t.attrs.iter().any(|a| a.path.is_ident("location"))
+}
 
 #[proc_macro_attribute]
 pub fn builtin(
@@ -8,14 +12,11 @@
 	item: proc_macro::TokenStream,
 ) -> proc_macro::TokenStream {
 	// syn::ItemFn::parse(input)
-	let fun: ItemFn = parse_macro_input!(item);
+	let mut fun: ItemFn = parse_macro_input!(item);
 
-	let inner_name = Ident::new("inner", Span::call_site());
-	let mut inner_fun = fun.clone();
-	inner_fun.sig.ident = inner_name.clone();
 	let result = match fun.sig.output {
 		syn::ReturnType::Default => panic!("builtin should return something"),
-		syn::ReturnType::Type(_, ty) => ty,
+		syn::ReturnType::Type(_, ref ty) => ty.clone(),
 	};
 
 	let params = fun
@@ -26,6 +27,7 @@
 			FnArg::Receiver(_) => unreachable!(),
 			FnArg::Typed(t) => t,
 		})
+		.filter(|a| !is_location_arg(a))
 		.map(|t| {
 			let ident = match &t.pat as &Pat {
 				Pat::Ident(i) => i.ident.to_string(),
@@ -39,38 +41,53 @@
 					has_default: #optional,
 				}
 			}
-		});
+		})
+		.collect::<Vec<_>>();
 
 	let args = fun
 		.sig
 		.inputs
-		.iter()
+		.iter_mut()
 		.map(|i| match i {
 			FnArg::Receiver(_) => unreachable!(),
 			FnArg::Typed(t) => t,
 		})
 		.map(|t| {
-			let ident = match &t.pat as &Pat {
-				Pat::Ident(i) => i.ident.to_string(),
-				_ => panic!("only idents supported yet"),
-			};
-			let ty = &t.ty;
-			quote! {{
-				let value = parsed.get(#ident).unwrap();
+			let count_before = t.attrs.len();
+			t.attrs.retain(|a| !a.path.is_ident("location"));
+			let count_after = t.attrs.len();
+			let is_location = count_before != count_after;
+			if is_location {
+				quote! {{
+					loc
+				}}
+			} else {
+				let ident = match &t.pat as &Pat {
+					Pat::Ident(i) => i.ident.to_string(),
+					_ => panic!("only idents supported yet"),
+				};
+				let ty = &t.ty;
+				quote! {{
+					let value = parsed.get(#ident).unwrap();
 
-				jrsonnet_evaluator::push_description_frame(
-					|| format!("argument <{}> evaluation", #ident),
-					|| <#ty>::try_from(value.evaluate()?),
-				)?
-			}}
-		});
+					jrsonnet_evaluator::push_description_frame(
+						|| format!("argument <{}> evaluation", #ident),
+						|| <#ty>::try_from(value.evaluate()?),
+					)?
+				}}
+			}
+		}).collect::<Vec<_>>();
+	
+	let inner_name = Ident::new("inner", Span::call_site());
+	let mut inner_fun = fun.clone();
+	inner_fun.sig.ident = inner_name.clone();
 
 	let attrs = &fun.attrs;
 	let vis = &fun.vis;
 	let name = &fun.sig.ident;
 	(quote! {
 		#(#attrs)*
-		#vis fn #name(context: Context, _loc: &ExprLocation, args: &ArgsDesc) -> Result<Val> {
+		#vis fn #name(context: Context, loc: &ExprLocation, args: &ArgsDesc) -> Result<Val> {
 			#inner_fun
 			use jrsonnet_evaluator::function::BuiltinParam;
 			const PARAMS: &'static [BuiltinParam] = &[
modifiedcrates/jrsonnet-types/src/lib.rsdiffbeforeafterboth
--- a/crates/jrsonnet-types/src/lib.rs
+++ b/crates/jrsonnet-types/src/lib.rs
@@ -191,9 +191,9 @@
 				write!(f, "}}")?;
 			}
 			ComplexValType::Union(v) => write_union(f, true, v.iter())?,
-			ComplexValType::UnionRef(v) => write_union(f, true, v.iter().map(|v| *v))?,
+			ComplexValType::UnionRef(v) => write_union(f, true, v.iter().copied())?,
 			ComplexValType::Sum(v) => write_union(f, false, v.iter())?,
-			ComplexValType::SumRef(v) => write_union(f, false, v.iter().map(|v| *v))?,
+			ComplexValType::SumRef(v) => write_union(f, false, v.iter().copied())?,
 		};
 		Ok(())
 	}
modifiedflake.nixdiffbeforeafterboth
--- a/flake.nix
+++ b/flake.nix
@@ -1,21 +1,59 @@
 {
-  description = "Rust jsonnet implementation";
-
-  inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
-  inputs.flake-utils.url = "github:numtide/flake-utils";
-
-  outputs = { self, nixpkgs, flake-utils }:
+  description = "Dotfiles manager";
+  inputs = {
+    nixpkgs.url = "github:nixos/nixpkgs";
+    flake-utils.url = "github:numtide/flake-utils";
+    naersk.url = "github:nix-community/naersk";
+    rust-overlay.url = "github:oxalica/rust-overlay";
+    pre-commit-hooks.url = "github:cachix/pre-commit-hooks.nix";
+  };
+  outputs = { self, nixpkgs, flake-utils, rust-overlay, pre-commit-hooks, naersk }:
     flake-utils.lib.eachDefaultSystem (system:
       let
-        pkgs = nixpkgs.legacyPackages.${system};
-        jrsonnet = pkgs.rustPlatform.buildRustPackage rec {
-          pname = "jrsonnet";
-          version = "0.1.0";
-          src = self;
-          cargoSha256 = "sha256-cez8pJ/uwj+PHAPQwpSB4CKaxcP8Uvv8xguOrVXR2xE=";
+        pkgs = import nixpkgs
+          {
+            inherit system;
+            overlays = [ rust-overlay.overlay ];
+          };
+        rust = ((pkgs.rustChannelOf { date = "2021-11-11"; channel = "nightly"; }).default.override {
+          extensions = [ "rust-src" ];
+        });
+        naersk-lib = naersk.lib."${system}".override {
+          rustc = rust;
+          cargo = rust;
+        };
+      in
+      rec {
+        checks = {
+          pre-commit-check = pre-commit-hooks.lib.${system}.run {
+            src = ./.;
+            hooks = {
+              nixpkgs-fmt.enable = true;
+            };
+          };
+        };
+        defaultPackage = naersk-lib.buildPackage {
+          pname = "dotman";
+          root = ./.;
+          buildInputs = with pkgs; [
+            pkgs.sqlite
+          ];
         };
-      in { 
-        defaultPackage = jrsonnet;
-        devShell = pkgs.mkShell {};
-      });
+        devShell = pkgs.mkShell {
+          inherit (checks.pre-commit-check) shellHook;
+          nativeBuildInputs = with pkgs;[
+            pkgs.binutils
+            pkgs.pkgconfig
+            pkgs.clang
+            pkgs.x11
+            pkgs.alsaLib
+            pkgs.libudev
+            pkgs.sqlite
+            rust
+            cargo-edit
+            go-jsonnet
+          ];
+        };
+      }
+    );
 }