Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion examples/minimal/ExampleOfEverything.tq
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ Ask these questions: are you really sure you want a coffee?

Assuming you do, then:

1. { repeat <making_coffee>(e) ~ cups }
1. { repeat <making_coffee>(e) }
a. First task
b. Second another task
'Yes' | 'No'
Expand All @@ -19,6 +19,7 @@ Assuming you do, then:
./stuff
```
) }
3. Write everything down ~ paper

another_example(e) : Input -> Output
{
Expand Down
32 changes: 27 additions & 5 deletions src/domain/engine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -146,13 +146,26 @@ impl<'i> Scope<'i> {
}
}

/// Returns the tablet pairs if this is a CodeBlock containing a Tablet.
pub fn tablet(&self) -> Option<&[Pair<'i>]> {
/// Returns the tablet pairs if this is a CodeBlock containing a single
/// list whose elements are all labelled values.
pub fn tablet(&self) -> Option<Vec<&Pair<'i>>> {
match self {
Scope::CodeBlock { expressions, .. } => {
if expressions.len() == 1 {
if let Expression::Tablet(pairs, _) = &expressions[0] {
return Some(pairs);
if let Expression::List(elements, _) = &expressions[0] {
let pairs: Vec<&Pair<'i>> = elements
.iter()
.filter_map(|element| {
if let Expression::Pair(pair, _) = element {
Some(pair.as_ref())
} else {
None
}
})
.collect();
if !pairs.is_empty() && pairs.len() == elements.len() {
return Some(pairs);
}
}
}
None
Expand Down Expand Up @@ -338,7 +351,16 @@ fn render_expression(expr: &Expression) -> String {
}
Expression::Number(Numeric::Scientific(q), _) => q.to_string(),
Expression::Number(Numeric::Integral(n), _) => n.to_string(),
Expression::Tablet(_, _) => String::new(),
Expression::Pair(pair, _) => {
format!("\"{}\" = {}", pair.label, render_expression(&pair.value))
}
Expression::List(elements, _) => {
let items: Vec<_> = elements
.iter()
.map(render_expression)
.collect();
format!("[{}]", items.join(", "))
}
Expression::Separator => String::new(),
}
}
Expand Down
100 changes: 77 additions & 23 deletions src/formatting/formatter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,31 @@ fn render_fragments<'i>(fragments: &[(Syntax, Cow<'i, str>)], renderer: &dyn Ren
result
}

/// A list reads as a tablet when it is non-empty and every element is a
/// labelled value. Such lists are laid out and treated as blocks rather than
/// inline.
fn is_tablet_list(elements: &[Expression]) -> bool {
!elements.is_empty()
&& elements
.iter()
.all(|element| {
if let Expression::Pair(_, _) = element {
true
} else {
false
}
})
}

/// True when an expression is a tablet-shaped list (see `is_tablet_list`).
fn is_tablet_list_expr(expr: &Expression) -> bool {
if let Expression::List(elements, _) = expr {
is_tablet_list(elements)
} else {
false
}
}

struct Formatter<'i> {
fragments: Vec<(Syntax, Cow<'i, str>)>,
nesting: u8,
Expand Down Expand Up @@ -329,8 +354,12 @@ impl<'i> Formatter<'i> {
}

fn render_inline_code(&self, expr: &'i Expression) -> Vec<(Syntax, Cow<'i, str>)> {
if is_tablet_list_expr(expr) {
// Not inline; caller handles the block layout specially.
return Vec::new();
}
match expr {
Expression::Tablet(_, _) | Expression::Multiline(_, _, _) => {
Expression::Multiline(_, _, _) => {
// These are not inline, caller should handle specially
Vec::new()
}
Expand Down Expand Up @@ -657,7 +686,7 @@ impl<'i> Formatter<'i> {
line.add_breakable(syntax, text);
}
Descriptive::CodeInline(expr) => match expr {
Expression::Tablet(_, _) => {
_ if is_tablet_list_expr(expr) => {
line.flush();
self.add_fragment_reference(Syntax::Structure, "{");
self.append_char('\n');
Expand Down Expand Up @@ -884,11 +913,7 @@ impl<'i> Formatter<'i> {
let inline = if has_separator {
true
} else if expressions.len() == 1 {
if let Expression::Tablet(_, _) = &expressions[0] {
false
} else {
true
}
!is_tablet_list_expr(&expressions[0])
} else {
false
};
Expand Down Expand Up @@ -1075,7 +1100,8 @@ impl<'i> Formatter<'i> {
self.add_fragment_reference(Syntax::Neutral, " ");
self.append_variables(variables);
}
Expression::Tablet(pairs, _) => self.append_tablet(pairs),
Expression::Pair(pair, _) => self.append_pair(pair),
Expression::List(elements, _) => self.append_list(elements),
Expression::Separator => {}
}
}
Expand Down Expand Up @@ -1205,25 +1231,53 @@ impl<'i> Formatter<'i> {
self.add_fragment_reference(Syntax::Structure, ")");
}

fn append_tablet(&mut self, pairs: &'i Vec<Pair>) {
self.add_fragment_reference(Syntax::Structure, "[");
self.append_char('\n');
fn append_pair(&mut self, pair: &'i Pair) {
self.add_fragment_reference(Syntax::Quote, "\"");
self.add_fragment_reference(Syntax::Label, pair.label);
self.add_fragment_reference(Syntax::Quote, "\"");
self.add_fragment_reference(Syntax::Neutral, " ");
self.add_fragment_reference(Syntax::Structure, "=");
self.add_fragment_reference(Syntax::Neutral, " ");
self.append_expression(&pair.value);
}

self.increase(4);
for pair in pairs {
self.indent();
self.add_fragment_reference(Syntax::Quote, "\"");
self.add_fragment_reference(Syntax::Label, pair.label);
self.add_fragment_reference(Syntax::Quote, "\"");
self.add_fragment_reference(Syntax::Neutral, " ");
self.add_fragment_reference(Syntax::Structure, "=");
self.add_fragment_reference(Syntax::Neutral, " ");
self.append_expression(&pair.value);
/// A list whose elements are all labelled (a tablet) is laid out one
/// element per line; any other list, and the empty list, is inline.
fn append_list(&mut self, elements: &'i Vec<Expression>) {
if elements.is_empty() {
self.add_fragment_reference(Syntax::Structure, "[]");
return;
}

if is_tablet_list(elements) {
self.add_fragment_reference(Syntax::Structure, "[");
self.append_char('\n');

self.increase(4);
for element in elements {
self.indent();
self.append_expression(element);
self.append_char('\n');
}
self.decrease(4);

self.indent();
self.add_fragment_reference(Syntax::Structure, "]");
return;
}
self.decrease(4);

self.indent();
self.add_fragment_reference(Syntax::Structure, "[");
for (i, element) in elements
.iter()
.enumerate()
{
if i > 0 {
self.add_fragment_reference(Syntax::Structure, ",");
}
self.add_fragment_reference(Syntax::Neutral, " ");
self.append_expression(element);
}
self.add_fragment_reference(Syntax::Neutral, " ");
self.add_fragment_reference(Syntax::Structure, "]");
}
}
Expand Down
6 changes: 4 additions & 2 deletions src/language/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -416,7 +416,8 @@ pub enum Expression<'i> {
Application(Invocation<'i>, Span),
Execution(Function<'i>, Span),
Binding(Box<Expression<'i>>, Vec<Identifier<'i>>, Span),
Tablet(Vec<Pair<'i>>, Span),
Pair(Box<Pair<'i>>, Span),
List(Vec<Expression<'i>>, Span),
Separator,
}

Expand All @@ -438,7 +439,8 @@ impl PartialEq for Expression<'_> {
(Expression::Binding(a1, a2, _), Expression::Binding(b1, b2, _)) => {
a1 == b1 && a2 == b2
}
(Expression::Tablet(a, _), Expression::Tablet(b, _)) => a == b,
(Expression::Pair(a, _), Expression::Pair(b, _)) => a == b,
(Expression::List(a, _), Expression::List(b, _)) => a == b,
(Expression::Separator, Expression::Separator) => true,
_ => false,
}
Expand Down
13 changes: 12 additions & 1 deletion src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -616,6 +616,17 @@ fn main() {

debug!(filename);

let arguments: Vec<String> = submatches
.get_many::<String>("arguments")
.map(|values| {
values
.cloned()
.collect()
})
.unwrap_or_default();

debug!(?arguments);

let filename = Path::new(filename);
let content = match parsing::load(&filename) {
Ok(data) => data,
Expand Down Expand Up @@ -670,7 +681,7 @@ fn main() {
}
};

match runner::start(filename, &program) {
match runner::start(filename, &program, &arguments) {
Ok((run_id, Outcome::Quit)) => {
eprintln!("paused; resume with `technique resume {}`", run_id.render());
std::process::exit(0);
Expand Down
Loading