Skip to content

Commit ce2d8d5

Browse files
authored
Merge pull request #19 from CertainLach/std-intrinsic
Prevent changing meaning of std in desugared expressions
2 parents 7e00c7d + 0a096fe commit ce2d8d5

File tree

7 files changed

+59
-66
lines changed

7 files changed

+59
-66
lines changed

crates/jrsonnet-evaluator/src/builtin/mod.rs

+32-33
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,12 @@ pub mod sort;
2020
pub fn call_builtin(
2121
context: Context,
2222
loc: &Option<ExprLocation>,
23-
ns: &str,
2423
name: &str,
2524
args: &ArgsDesc,
2625
) -> Result<Val> {
27-
Ok(match (ns, name as &str) {
26+
Ok(match name as &str {
2827
// arr/string/function
29-
("std", "length") => parse_args!(context, "std.length", args, 1, [
28+
"length" => parse_args!(context, "std.length", args, 1, [
3029
0, x: [Val::Str|Val::Arr|Val::Obj], vec![ValType::Str, ValType::Arr, ValType::Obj];
3130
], {
3231
Ok(match x {
@@ -42,13 +41,13 @@ pub fn call_builtin(
4241
})
4342
})?,
4443
// any
45-
("std", "type") => parse_args!(context, "std.type", args, 1, [
44+
"type" => parse_args!(context, "std.type", args, 1, [
4645
0, x, vec![];
4746
], {
4847
Ok(Val::Str(x.value_type()?.name().into()))
4948
})?,
5049
// length, idx=>any
51-
("std", "makeArray") => parse_args!(context, "std.makeArray", args, 2, [
50+
"makeArray" => parse_args!(context, "std.makeArray", args, 2, [
5251
0, sz: [Val::Num]!!Val::Num, vec![ValType::Num];
5352
1, func: [Val::Func]!!Val::Func, vec![ValType::Func];
5453
], {
@@ -65,7 +64,7 @@ pub fn call_builtin(
6564
Ok(Val::Arr(Rc::new(out)))
6665
})?,
6766
// string
68-
("std", "codepoint") => parse_args!(context, "std.codepoint", args, 1, [
67+
"codepoint" => parse_args!(context, "std.codepoint", args, 1, [
6968
0, str: [Val::Str]!!Val::Str, vec![ValType::Str];
7069
], {
7170
assert!(
@@ -75,7 +74,7 @@ pub fn call_builtin(
7574
Ok(Val::Num(str.chars().take(1).next().unwrap() as u32 as f64))
7675
})?,
7776
// object, includeHidden
78-
("std", "objectFieldsEx") => parse_args!(context, "std.objectFieldsEx",args, 2, [
77+
"objectFieldsEx" => parse_args!(context, "std.objectFieldsEx",args, 2, [
7978
0, obj: [Val::Obj]!!Val::Obj, vec![ValType::Obj];
8079
1, inc_hidden: [Val::Bool]!!Val::Bool, vec![ValType::Bool];
8180
], {
@@ -88,7 +87,7 @@ pub fn call_builtin(
8887
Ok(Val::Arr(Rc::new(out.into_iter().map(Val::Str).collect())))
8988
})?,
9089
// object, field, includeHidden
91-
("std", "objectHasEx") => parse_args!(context, "std.objectHasEx", args, 3, [
90+
"objectHasEx" => parse_args!(context, "std.objectHasEx", args, 3, [
9291
0, obj: [Val::Obj]!!Val::Obj, vec![ValType::Obj];
9392
1, f: [Val::Str]!!Val::Str, vec![ValType::Str];
9493
2, inc_hidden: [Val::Bool]!!Val::Bool, vec![ValType::Bool];
@@ -100,36 +99,36 @@ pub fn call_builtin(
10099
.any(|(k, _v)| *k == *f),
101100
))
102101
})?,
103-
("std", "primitiveEquals") => parse_args!(context, "std.primitiveEquals", args, 2, [
102+
"primitiveEquals" => parse_args!(context, "std.primitiveEquals", args, 2, [
104103
0, a, vec![];
105104
1, b, vec![];
106105
], {
107106
Ok(Val::Bool(primitive_equals(&a, &b)?))
108107
})?,
109108
// faster
110-
("std", "equals") => parse_args!(context, "std.equals", args, 2, [
109+
"equals" => parse_args!(context, "std.equals", args, 2, [
111110
0, a, vec![];
112111
1, b, vec![];
113112
], {
114113
Ok(Val::Bool(equals(&a, &b)?))
115114
})?,
116-
("std", "modulo") => parse_args!(context, "std.modulo", args, 2, [
115+
"modulo" => parse_args!(context, "std.modulo", args, 2, [
117116
0, a: [Val::Num]!!Val::Num, vec![ValType::Num];
118117
1, b: [Val::Num]!!Val::Num, vec![ValType::Num];
119118
], {
120119
Ok(Val::Num(a % b))
121120
})?,
122-
("std", "floor") => parse_args!(context, "std.floor", args, 1, [
121+
"floor" => parse_args!(context, "std.floor", args, 1, [
123122
0, x: [Val::Num]!!Val::Num, vec![ValType::Num];
124123
], {
125124
Ok(Val::Num(x.floor()))
126125
})?,
127-
("std", "log") => parse_args!(context, "std.log", args, 2, [
126+
"log" => parse_args!(context, "std.log", args, 2, [
128127
0, n: [Val::Num]!!Val::Num, vec![ValType::Num];
129128
], {
130129
Ok(Val::Num(n.ln()))
131130
})?,
132-
("std", "trace") => parse_args!(context, "std.trace", args, 2, [
131+
"trace" => parse_args!(context, "std.trace", args, 2, [
133132
0, str: [Val::Str]!!Val::Str, vec![ValType::Str];
134133
1, rest, vec![];
135134
], {
@@ -143,27 +142,27 @@ pub fn call_builtin(
143142
eprintln!(" {}", str);
144143
Ok(rest)
145144
})?,
146-
("std", "pow") => parse_args!(context, "std.modulo", args, 2, [
145+
"pow" => parse_args!(context, "std.modulo", args, 2, [
147146
0, x: [Val::Num]!!Val::Num, vec![ValType::Num];
148147
1, n: [Val::Num]!!Val::Num, vec![ValType::Num];
149148
], {
150149
Ok(Val::Num(x.powf(n)))
151150
})?,
152-
("std", "extVar") => parse_args!(context, "std.extVar", args, 1, [
151+
"extVar" => parse_args!(context, "std.extVar", args, 1, [
153152
0, x: [Val::Str]!!Val::Str, vec![ValType::Str];
154153
], {
155154
Ok(with_state(|s| s.settings().ext_vars.get(&x).cloned()).ok_or_else(
156155
|| UndefinedExternalVariable(x),
157156
)?)
158157
})?,
159-
("std", "native") => parse_args!(context, "std.native", args, 1, [
158+
"native" => parse_args!(context, "std.native", args, 1, [
160159
0, x: [Val::Str]!!Val::Str, vec![ValType::Str];
161160
], {
162161
Ok(with_state(|s| s.settings().ext_natives.get(&x).cloned()).map(|v| Val::Func(Rc::new(FuncVal::NativeExt(x.clone(), v)))).ok_or_else(
163162
|| UndefinedExternalFunction(x),
164163
)?)
165164
})?,
166-
("std", "filter") => parse_args!(context, "std.filter", args, 2, [
165+
"filter" => parse_args!(context, "std.filter", args, 2, [
167166
0, func: [Val::Func]!!Val::Func, vec![ValType::Func];
168167
1, arr: [Val::Arr]!!Val::Arr, vec![ValType::Arr];
169168
], {
@@ -181,7 +180,7 @@ pub fn call_builtin(
181180
)))
182181
})?,
183182
// faster
184-
("std", "foldl") => parse_args!(context, "std.foldl", args, 3, [
183+
"foldl" => parse_args!(context, "std.foldl", args, 3, [
185184
0, func: [Val::Func]!!Val::Func, vec![ValType::Func];
186185
1, arr: [Val::Arr]!!Val::Arr, vec![ValType::Arr];
187186
2, init, vec![];
@@ -193,7 +192,7 @@ pub fn call_builtin(
193192
Ok(acc)
194193
})?,
195194
// faster
196-
("std", "foldr") => parse_args!(context, "std.foldr", args, 3, [
195+
"foldr" => parse_args!(context, "std.foldr", args, 3, [
197196
0, func: [Val::Func]!!Val::Func, vec![ValType::Func];
198197
1, arr: [Val::Arr]!!Val::Arr, vec![ValType::Arr];
199198
2, init, vec![];
@@ -206,7 +205,7 @@ pub fn call_builtin(
206205
})?,
207206
// faster
208207
#[allow(non_snake_case)]
209-
("std", "sortImpl") => parse_args!(context, "std.sort", args, 2, [
208+
"sortImpl" => parse_args!(context, "std.sort", args, 2, [
210209
0, arr: [Val::Arr]!!Val::Arr, vec![ValType::Arr];
211210
1, keyF: [Val::Func]!!Val::Func, vec![ValType::Func];
212211
], {
@@ -216,7 +215,7 @@ pub fn call_builtin(
216215
Ok(Val::Arr(sort::sort(context, arr, &keyF)?))
217216
})?,
218217
// faster
219-
("std", "format") => parse_args!(context, "std.format", args, 2, [
218+
"format" => parse_args!(context, "std.format", args, 2, [
220219
0, str: [Val::Str]!!Val::Str, vec![ValType::Str];
221220
1, vals, vec![]
222221
], {
@@ -229,7 +228,7 @@ pub fn call_builtin(
229228
})
230229
})?,
231230
// faster
232-
("std", "range") => parse_args!(context, "std.range", args, 2, [
231+
"range" => parse_args!(context, "std.range", args, 2, [
233232
0, from: [Val::Num]!!Val::Num, vec![ValType::Num];
234233
1, to: [Val::Num]!!Val::Num, vec![ValType::Num];
235234
], {
@@ -239,7 +238,7 @@ pub fn call_builtin(
239238
}
240239
Ok(Val::Arr(Rc::new(out)))
241240
})?,
242-
("std", "char") => parse_args!(context, "std.char", args, 1, [
241+
"char" => parse_args!(context, "std.char", args, 1, [
243242
0, n: [Val::Num]!!Val::Num, vec![ValType::Num];
244243
], {
245244
let mut out = String::new();
@@ -248,18 +247,18 @@ pub fn call_builtin(
248247
)?);
249248
Ok(Val::Str(out.into()))
250249
})?,
251-
("std", "encodeUTF8") => parse_args!(context, "std.encodeUtf8", args, 1, [
250+
"encodeUTF8" => parse_args!(context, "std.encodeUtf8", args, 1, [
252251
0, str: [Val::Str]!!Val::Str, vec![ValType::Str];
253252
], {
254253
Ok(Val::Arr(Rc::new(str.bytes().map(|b| Val::Num(b as f64)).collect())))
255254
})?,
256-
("std", "md5") => parse_args!(context, "std.md5", args, 1, [
255+
"md5" => parse_args!(context, "std.md5", args, 1, [
257256
0, str: [Val::Str]!!Val::Str, vec![ValType::Str];
258257
], {
259258
Ok(Val::Str(format!("{:x}", md5::compute(&str.as_bytes())).into()))
260259
})?,
261260
// faster
262-
("std", "base64") => parse_args!(context, "std.base64", args, 1, [
261+
"base64" => parse_args!(context, "std.base64", args, 1, [
263262
0, input: [Val::Str | Val::Arr], vec![ValType::Arr, ValType::Str];
264263
], {
265264
Ok(Val::Str(match input {
@@ -275,7 +274,7 @@ pub fn call_builtin(
275274
}))
276275
})?,
277276
// faster
278-
("std", "join") => parse_args!(context, "std.join", args, 2, [
277+
"join" => parse_args!(context, "std.join", args, 2, [
279278
0, sep: [Val::Str|Val::Arr], vec![ValType::Str, ValType::Arr];
280279
1, arr: [Val::Arr]!!Val::Arr, vec![ValType::Arr];
281280
], {
@@ -322,13 +321,13 @@ pub fn call_builtin(
322321
})
323322
})?,
324323
// Faster
325-
("std", "escapeStringJson") => parse_args!(context, "std.escapeStringJson", args, 1, [
324+
"escapeStringJson" => parse_args!(context, "std.escapeStringJson", args, 1, [
326325
0, str_: [Val::Str]!!Val::Str, vec![ValType::Str];
327326
], {
328327
Ok(Val::Str(escape_string_json(&str_).into()))
329328
})?,
330329
// Faster
331-
("std", "manifestJsonEx") => parse_args!(context, "std.manifestJsonEx", args, 2, [
330+
"manifestJsonEx" => parse_args!(context, "std.manifestJsonEx", args, 2, [
332331
0, value, vec![];
333332
1, indent: [Val::Str]!!Val::Str, vec![ValType::Str];
334333
], {
@@ -338,18 +337,18 @@ pub fn call_builtin(
338337
})?.into()))
339338
})?,
340339
// Faster
341-
("std", "reverse") => parse_args!(context, "std.reverse", args, 1, [
340+
"reverse" => parse_args!(context, "std.reverse", args, 1, [
342341
0, arr: [Val::Arr]!!Val::Arr, vec![ValType::Arr];
343342
], {
344343
let mut marr = arr;
345344
Rc::make_mut(&mut marr).reverse();
346345
Ok(Val::Arr(marr))
347346
})?,
348-
("std", "id") => parse_args!(context, "std.id", args, 1, [
347+
"id" => parse_args!(context, "std.id", args, 1, [
349348
0, v, vec![];
350349
], {
351350
Ok(v)
352351
})?,
353-
(ns, name) => throw!(IntrinsicNotFound(ns.into(), name.into())),
352+
name => throw!(IntrinsicNotFound(name.into())),
354353
})
355354
}

crates/jrsonnet-evaluator/src/error.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ use thiserror::Error;
88

99
#[derive(Error, Debug, Clone)]
1010
pub enum Error {
11-
#[error("intrinsic not found: {0}.{1}")]
12-
IntrinsicNotFound(Rc<str>, Rc<str>),
11+
#[error("intrinsic not found: {0}")]
12+
IntrinsicNotFound(Rc<str>),
1313
#[error("argument reordering in intrisics not supported yet")]
1414
IntrinsicArgumentReorderingIsNotSupportedYet,
1515

crates/jrsonnet-evaluator/src/evaluate.rs

+3-4
Original file line numberDiff line numberDiff line change
@@ -466,10 +466,8 @@ pub fn evaluate(context: Context, expr: &LocExpr) -> Result<Val> {
466466
|| {
467467
if let Some(v) = v.get(s.clone())? {
468468
Ok(v.unwrap_if_lazy()?)
469-
} else if let Some(Val::Str(n)) =
470-
v.get("__intrinsic_namespace__".into())?
471-
{
472-
Ok(Val::Func(Rc::new(FuncVal::Intrinsic(n, s))))
469+
} else if v.get("__intrinsic_namespace__".into())?.is_some() {
470+
Ok(Val::Func(Rc::new(FuncVal::Intrinsic(s))))
473471
} else {
474472
throw!(NoSuchField(s))
475473
}
@@ -558,6 +556,7 @@ pub fn evaluate(context: Context, expr: &LocExpr) -> Result<Val> {
558556
Function(params, body) => {
559557
evaluate_method(context, "anonymous".into(), params.clone(), body.clone())
560558
}
559+
Intrinsic(name) => Val::Func(Rc::new(FuncVal::Intrinsic(name.clone()))),
561560
AssertExpr(AssertStmt(value, msg), returned) => {
562561
let assertion_result = push(
563562
&value.1,

crates/jrsonnet-evaluator/src/lib.rs

+8
Original file line numberDiff line numberDiff line change
@@ -893,4 +893,12 @@ pub mod tests {
893893
)?;
894894
Ok(())
895895
}
896+
897+
#[test]
898+
fn constant_intrinsic() -> crate::error::Result<()> {
899+
assert_eval!(
900+
"local std2 = std; local std = std2 { primitiveEquals(a, b):: false }; 1 == 1"
901+
);
902+
Ok(())
903+
}
896904
}

crates/jrsonnet-evaluator/src/val.rs

+7-7
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ pub enum FuncVal {
7676
/// Plain function implemented in jsonnet
7777
Normal(FuncDesc),
7878
/// Standard library function
79-
Intrinsic(Rc<str>, Rc<str>),
79+
Intrinsic(Rc<str>),
8080
/// Library functions implemented in native
8181
NativeExt(Rc<str>, Rc<NativeCallback>),
8282
}
@@ -85,20 +85,20 @@ impl PartialEq for FuncVal {
8585
fn eq(&self, other: &Self) -> bool {
8686
match (self, other) {
8787
(Self::Normal(a), Self::Normal(b)) => a == b,
88-
(Self::Intrinsic(ans, an), Self::Intrinsic(bns, bn)) => ans == bns && an == bn,
88+
(Self::Intrinsic(an), Self::Intrinsic(bn)) => an == bn,
8989
(Self::NativeExt(an, _), Self::NativeExt(bn, _)) => an == bn,
9090
(..) => false,
9191
}
9292
}
9393
}
9494
impl FuncVal {
9595
pub fn is_ident(&self) -> bool {
96-
matches!(&self, Self::Intrinsic(ns, n) if ns as &str == "std" && n as &str == "id")
96+
matches!(&self, Self::Intrinsic(n) if n as &str == "id")
9797
}
9898
pub fn name(&self) -> Rc<str> {
9999
match self {
100100
Self::Normal(normal) => normal.name.clone(),
101-
Self::Intrinsic(ns, name) => format!("intrinsic.{}.{}", ns, name).into(),
101+
Self::Intrinsic(name) => format!("std.{}", name).into(),
102102
Self::NativeExt(n, _) => format!("native.{}", n).into(),
103103
}
104104
}
@@ -120,7 +120,7 @@ impl FuncVal {
120120
)?;
121121
evaluate(ctx, &func.body)
122122
}
123-
Self::Intrinsic(ns, name) => call_builtin(call_ctx, loc, ns, name, args),
123+
Self::Intrinsic(name) => call_builtin(call_ctx, loc, name, args),
124124
Self::NativeExt(_name, handler) => {
125125
let args = parse_function_call(call_ctx, None, &handler.params, args, true)?;
126126
let mut out_args = Vec::with_capacity(handler.params.len());
@@ -149,7 +149,7 @@ impl FuncVal {
149149
)?;
150150
evaluate(ctx, &func.body)
151151
}
152-
Self::Intrinsic(_, _) => todo!(),
152+
Self::Intrinsic(_) => todo!(),
153153
Self::NativeExt(_, _) => todo!(),
154154
}
155155
}
@@ -160,7 +160,7 @@ impl FuncVal {
160160
let ctx = place_args(call_ctx, Some(func.ctx.clone()), &func.params, args)?;
161161
evaluate(ctx, &func.body)
162162
}
163-
Self::Intrinsic(_, _) => todo!(),
163+
Self::Intrinsic(_) => todo!(),
164164
Self::NativeExt(_, _) => todo!(),
165165
}
166166
}

crates/jrsonnet-parser/src/expr.rs

+2
Original file line numberDiff line numberDiff line change
@@ -311,6 +311,8 @@ pub enum Expr {
311311
Index(LocExpr, LocExpr),
312312
/// function(x) x
313313
Function(ParamsDesc, LocExpr),
314+
/// std.primitiveEquals
315+
Intrinsic(Rc<str>),
314316
/// if true == false then 1 else 2
315317
IfElse {
316318
cond: IfSpecData,

0 commit comments

Comments
 (0)