Skip to content

Commit 9806586

Browse files
authored
Handle break labels like variables.
2 parents d3b7d95 + faae800 commit 9806586

File tree

5 files changed

+212
-179
lines changed

5 files changed

+212
-179
lines changed

jaq-core/src/compile.rs

Lines changed: 75 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,14 @@
11
//! Program compilation.
22
33
use crate::load::{self, lex, parse};
4-
use crate::{ops, Bind, Filter};
4+
use crate::{ops, Bind as Arg, Filter};
55
use alloc::collections::{BTreeMap, BTreeSet};
66
use alloc::{boxed::Box, string::String, vec::Vec};
77

88
type NativeId = usize;
99
type ModId = usize;
1010
type VarId = usize;
1111
type VarSkip = usize;
12-
type LabelSkip = usize;
1312
type Arity = usize;
1413

1514
/// Index of a term in the look-up table.
@@ -81,15 +80,14 @@ pub(crate) enum Term<T = TermId> {
8180
/// Singleton object (`{f: g}`)
8281
ObjSingle(T, T),
8382

84-
/// Bound variable (`$x`) or filter argument (`a`)
85-
Var(VarId, LabelSkip),
83+
/// Bound variable (`$x`), label (`label $x`), or filter argument (`a`)
84+
Var(VarId),
8685
/// Call to a filter (`filter`, `filter(…)`)
87-
CallDef(TermId, Box<[Bind<T>]>, VarSkip, Option<Tailrec>),
88-
Native(NativeId, Box<[Bind<T>]>),
86+
CallDef(TermId, Box<[Arg<T>]>, VarSkip, Option<Tailrec>),
87+
Native(NativeId, Box<[Arg<T>]>),
8988

89+
/// Binding of a break label (`label $x | f`)
9090
Label(T),
91-
Break(usize),
92-
9391
/// Negation operation (`-f`)
9492
Neg(T),
9593
/// Variable binding (`f as $x | g`) if identifier (`x`) is given, otherwise
@@ -233,22 +231,22 @@ impl<S: Default, F> Default for Compiler<S, F> {
233231
}
234232

235233
#[derive(Clone, Debug)]
236-
struct Sig<S, A = Bind> {
234+
struct Sig<S, A = Arg> {
237235
name: S,
238236
// TODO: we could analyse for each argument whether it is TR, and
239237
// use this when converting args at callsite
240238
args: Box<[A]>,
241239
}
242240

243-
fn bind_from<T>(s: &str, x: T) -> Bind<T> {
241+
fn bind_from<T>(s: &str, x: T) -> Arg<T> {
244242
if s.starts_with('$') {
245-
Bind::Var(x)
243+
Arg::Var(x)
246244
} else {
247-
Bind::Fun(x)
245+
Arg::Fun(x)
248246
}
249247
}
250248

251-
fn binds<T, U: Copy>(binds: &[Bind<T>], args: &[U]) -> Box<[Bind<U>]> {
249+
fn binds<T, U: Copy>(binds: &[Arg<T>], args: &[U]) -> Box<[Arg<U>]> {
252250
assert!(binds.len() == args.len());
253251
let args = binds.iter().zip(args);
254252
args.map(|(bind, id)| bind.as_ref().map(|_| *id)).collect()
@@ -270,7 +268,7 @@ impl<S: Eq, A> Sig<S, A> {
270268
}
271269

272270
impl Def {
273-
fn call(&self, args: Box<[Bind<TermId>]>, vars: usize) -> Term {
271+
fn call(&self, args: Box<[Arg<TermId>]>, vars: usize) -> Term {
274272
// we pretend that the function call is tail-recursive,
275273
// and at the very end of compilation, we will correct calls
276274
// to non-tail-recursive functions
@@ -279,12 +277,20 @@ impl Def {
279277
}
280278

281279
/// Store a map of vectors plus the sum of the lengths of all vectors.
282-
#[derive(Default)]
283280
struct MapVecLen<S> {
284281
bound: MapVec<S, usize>,
285282
total: usize,
286283
}
287284

285+
impl<S> Default for MapVecLen<S> {
286+
fn default() -> Self {
287+
Self {
288+
bound: MapVec::default(),
289+
total: 0,
290+
}
291+
}
292+
}
293+
288294
impl<S: Ord> MapVecLen<S> {
289295
fn push(&mut self, name: S) {
290296
self.total += 1;
@@ -302,22 +308,40 @@ impl<S: Ord> MapVecLen<S> {
302308
}
303309

304310
enum Fun<S> {
305-
// number of labels
306-
Arg(usize),
307-
Parent(Box<[Bind<S>]>, Def),
311+
Arg,
312+
Parent(Box<[Arg<S>]>, Def),
308313
// Tr is for tail-rec allowed funs
309-
Sibling(Box<[Bind<S>]>, Def, Tr),
314+
Sibling(Box<[Arg<S>]>, Def, Tr),
315+
}
316+
317+
/// Single binding.
318+
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
319+
pub(crate) enum Bind<V, L = V, F = V> {
320+
/// binding to a variable
321+
Var(V),
322+
/// binding to a break label
323+
Label(L),
324+
/// binding to a filter
325+
Fun(F),
310326
}
311327

312-
#[derive(Default)]
313328
struct Locals<S> {
314329
// usize = number of vars
315330
funs: MapVec<(S, Arity), (Fun<S>, usize)>,
316-
vars: MapVecLen<S>,
317-
labels: MapVecLen<S>,
331+
vars: MapVecLen<Bind<S>>,
318332
parents: Tr,
319333
}
320334

335+
impl<S> Default for Locals<S> {
336+
fn default() -> Self {
337+
Self {
338+
funs: MapVec::default(),
339+
vars: MapVecLen::default(),
340+
parents: Tr::default(),
341+
}
342+
}
343+
}
344+
321345
struct MapVec<K, V>(BTreeMap<K, Vec<V>>);
322346

323347
impl<K, V> Default for MapVec<K, V> {
@@ -354,15 +378,15 @@ impl<K: Ord, V> MapVec<K, V> {
354378
}
355379

356380
impl<S: Copy + Ord> Locals<S> {
357-
fn push_sibling(&mut self, name: S, args: Box<[Bind<S>]>, def: Def) {
381+
fn push_sibling(&mut self, name: S, args: Box<[Arg<S>]>, def: Def) {
358382
let tr = self.parents.clone();
359383
self.funs.push(
360384
(name, args.len()),
361385
(Fun::Sibling(args, def, tr), self.vars.total),
362386
);
363387
}
364388

365-
fn pop_sibling(&mut self, name: S, arity: Arity) -> (Box<[Bind<S>]>, Def, Tr) {
389+
fn pop_sibling(&mut self, name: S, arity: Arity) -> (Box<[Arg<S>]>, Def, Tr) {
366390
let (y, vars) = match self.funs.pop(&(name, arity)) {
367391
Some((Fun::Sibling(args, def, tr), vars)) => ((args, def, tr), vars),
368392
_ => panic!(),
@@ -371,15 +395,15 @@ impl<S: Copy + Ord> Locals<S> {
371395
y
372396
}
373397

374-
fn push_parent(&mut self, name: S, args: Box<[Bind<S>]>, def: Def) {
398+
fn push_parent(&mut self, name: S, args: Box<[Arg<S>]>, def: Def) {
375399
self.parents.insert(def.id);
376400

377401
let vars = self.vars.total;
378402

379403
for arg in args.iter() {
380404
match arg {
381-
Bind::Var(v) => self.vars.push(*v),
382-
Bind::Fun(f) => self.push_arg(*f),
405+
Arg::Var(v) => self.vars.push(Bind::Var(*v)),
406+
Arg::Fun(f) => self.push_arg(*f),
383407
}
384408
}
385409

@@ -394,8 +418,8 @@ impl<S: Copy + Ord> Locals<S> {
394418
};
395419
for arg in args.iter().rev() {
396420
match arg {
397-
Bind::Var(v) => self.vars.pop(v),
398-
Bind::Fun(f) => self.pop_arg(*f),
421+
Arg::Var(v) => self.vars.pop(&Bind::Var(*v)),
422+
Arg::Fun(f) => self.pop_arg(*f),
399423
}
400424
}
401425
assert_eq!(self.vars.total, vars);
@@ -404,26 +428,22 @@ impl<S: Copy + Ord> Locals<S> {
404428
}
405429

406430
fn push_arg(&mut self, name: S) {
407-
self.vars.total += 1;
408-
self.funs
409-
.push((name, 0), (Fun::Arg(self.labels.total), self.vars.total));
431+
self.vars.push(Bind::Fun(name));
432+
self.funs.push((name, 0), (Fun::Arg, self.vars.total));
410433
}
411434

412435
fn pop_arg(&mut self, name: S) {
413-
let (labels, vars) = match self.funs.pop(&(name, 0)) {
414-
Some((Fun::Arg(labels), vars)) => (labels, vars),
436+
let vars = match self.funs.pop(&(name, 0)) {
437+
Some((Fun::Arg, vars)) => vars,
415438
_ => panic!(),
416439
};
417-
assert_eq!(self.labels.total, labels);
418440
assert_eq!(self.vars.total, vars);
419-
self.vars.total -= 1;
441+
self.vars.pop(&Bind::Fun(name));
420442
}
421443

422444
fn call(&mut self, name: S, args: &[TermId], tr: &Tr) -> Option<Term> {
423445
Some(match self.funs.get_last_mut(&(name, args.len()))? {
424-
(Fun::Arg(labels), vars) => {
425-
Term::Var(self.vars.total - *vars, self.labels.total - *labels)
426-
}
446+
(Fun::Arg, vars) => Term::Var(self.vars.total - *vars),
427447
(Fun::Sibling(args_, def, tr_), vars) => {
428448
// we are at a position that may only call `tr` tail-recursively and
429449
// we call a sibling that may only call `tr_` tail-recursively,
@@ -447,10 +467,7 @@ impl<S: Copy + Ord> Locals<S> {
447467
}
448468

449469
fn is_empty(&self) -> bool {
450-
self.funs.is_empty()
451-
&& self.vars.is_empty()
452-
&& self.labels.is_empty()
453-
&& self.parents.is_empty()
470+
self.funs.is_empty() && self.vars.is_empty() && self.parents.is_empty()
454471
}
455472
}
456473

@@ -460,7 +477,7 @@ type Tr = BTreeSet<TermId>;
460477

461478
impl<'s, F> Compiler<&'s str, F> {
462479
/// Supply functions with given signatures.
463-
pub fn with_funs(mut self, funs: impl IntoIterator<Item = (&'s str, Box<[Bind]>, F)>) -> Self {
480+
pub fn with_funs(mut self, funs: impl IntoIterator<Item = (&'s str, Box<[Arg]>, F)>) -> Self {
464481
self.lut.funs = funs
465482
.into_iter()
466483
.map(|(name, args, f)| (Sig { name, args }, f))
@@ -533,16 +550,19 @@ impl<'s, F> Compiler<&'s str, F> {
533550
}
534551

535552
fn with_label<T>(&mut self, label: &'s str, f: impl FnOnce(&mut Self) -> T) -> T {
536-
self.locals.labels.push(label);
553+
self.locals.vars.push(Bind::Label(label));
537554
let y = f(self);
538-
self.locals.labels.pop(&label);
555+
self.locals.vars.pop(&Bind::Label(label));
539556
y
540557
}
541558

542559
fn with_vars<T>(&mut self, vars: &[&'s str], f: impl FnOnce(&mut Self) -> T) -> T {
543-
vars.iter().for_each(|v| self.locals.vars.push(v));
560+
vars.iter()
561+
.for_each(|v| self.locals.vars.push(Bind::Var(v)));
544562
let y = f(self);
545-
vars.iter().rev().for_each(|v| self.locals.vars.pop(v));
563+
vars.iter()
564+
.rev()
565+
.for_each(|v| self.locals.vars.pop(&Bind::Var(v)));
546566
y
547567
}
548568

@@ -583,7 +603,7 @@ impl<'s, F> Compiler<&'s str, F> {
583603
}
584604

585605
/// Compile a placeholder sibling with its corresponding definition.
586-
fn def_post(&mut self, d: parse::Def<&'s str>) -> (Sig<&'s str, Bind>, Def) {
606+
fn def_post(&mut self, d: parse::Def<&'s str>) -> (Sig<&'s str, Arg>, Def) {
587607
let (args, def, mut tr) = self.locals.pop_sibling(d.name, d.args.len());
588608
let tid = def.id;
589609
self.locals.push_parent(d.name, args, def);
@@ -808,19 +828,19 @@ impl<'s, F> Compiler<&'s str, F> {
808828
fn var(&mut self, x: &'s str) -> Term {
809829
let mut i = self.locals.vars.total;
810830

811-
if let Some(v) = self.locals.vars.bound.get_last(&x) {
812-
return Term::Var(i - v, 0);
831+
if let Some(v) = self.locals.vars.bound.get_last(&Bind::Var(x)) {
832+
return Term::Var(i - v);
813833
}
814834
for (x_, mid) in self.imported_vars.iter().rev() {
815835
if x == *x_ && *mid == self.mod_map.len() {
816-
return Term::Var(i, 0);
836+
return Term::Var(i);
817837
} else {
818838
i += 1;
819839
}
820840
}
821841
for x_ in self.global_vars.iter().rev() {
822842
if x == *x_ {
823-
return Term::Var(i, 0);
843+
return Term::Var(i);
824844
} else {
825845
i += 1;
826846
}
@@ -829,8 +849,8 @@ impl<'s, F> Compiler<&'s str, F> {
829849
}
830850

831851
fn break_(&mut self, x: &'s str) -> Term {
832-
if let Some(l) = self.locals.labels.bound.get_last(&x) {
833-
return Term::Break(self.locals.labels.total - l);
852+
if let Some(l) = self.locals.vars.bound.get_last(&Bind::Label(x)) {
853+
return Term::Var(self.locals.vars.total - l);
834854
}
835855
self.fail(x, Undefined::Label)
836856
}

jaq-core/src/exn.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ pub(crate) enum Inner<'a, V> {
1717
///
1818
/// This is used internally to execute tail-recursive filters.
1919
/// If this can be observed by users, then this is a bug.
20-
TailCall(&'a crate::compile::TermId, crate::Vars<'a, V>, V),
20+
TailCall(&'a crate::compile::TermId, crate::filter::Vars<'a, V>, V),
2121
Break(usize),
2222
}
2323

0 commit comments

Comments
 (0)