Ensure {} is a dict, not a set

This fixes the json compatibility issue. Also update some terminology
from "record" to "dict" now that I'm touching things anyway.
This commit is contained in:
Ruud van Asseldonk 2023-09-24 12:28:06 +02:00
parent 5964173067
commit be73b4a2c2
9 changed files with 31 additions and 25 deletions

View file

@ -59,11 +59,12 @@ allowed but not required.
["Eggplant", "Pepper", "Zuccini"],
]
## Records
## Dictionaries
Records are surrounded by `{}`. Records can be written in json form, where the
left-hand side is an expression. Then the key and value are separated by `:` and
the element separator is `,`. A trailing comma is optional.
Dictionaries, _dicts_ for short, are surrounded by `{}`. Dicts can be written
in json form, where the left-hand side is an expression. Then the key and value
are separated by `:` and the element separator is `,`. A trailing comma is
optional.
{
"name": "apple",
@ -79,7 +80,7 @@ strings precludes serialization to json.
5 + 5: "X",
}
Alternatively, records can be written in record form, where the left-hand side
Alternatively, dicts can be written in record form, where the left-hand side
is an identifier. Then the key and value are separated by `=` and the element
separator is `;`. A trailing semicolon is optional. The following value is
identical to the first one above.
@ -89,20 +90,25 @@ identical to the first one above.
flavor = "sweet";
}
Note, the empty collection `{}` is a set, not a record.
TODO: It _has_ to be a record, because in json it is a record. Need to fix!
Note, the empty collection `{}` is a dict, not a set.
## Sets
Sets are surrounded by `{}` and work otherwise the same as lists. The empty
collection `{}` is a set, not a record. The following list contains two
identical sets:
Sets are surrounded by `{}` and work otherwise the same as lists. The following
list contains two identical sets:
[
{"Apple", "Pear"},
{"Apple", "Pear", "Apple"},
]
Note, the empty collection `{}` is a dict, not a set. There is currently no
literal for the empty set. It is possible to work around this using
comprehensions:
// An empty set.
{for x in []: x}
## Let bindings
Values can be bound to names with a let-binding.

View file

@ -14,4 +14,4 @@ Error: Expected key-value, not a scalar element.
|
2 | "key": "value",
| ^
Note: The collection is a record and not a set, because of this key-value.
Note: The collection is a dict and not a set, because of this key-value.

View file

@ -7,4 +7,4 @@
| ^
Error: Expected scalar element, not key-value.
Help: Key-value pairs are allowed in records, which are enclosed in '{}', not '[]'.
Help: Key-value pairs are allowed in dicts, which are enclosed in '{}', not '[]'.

View file

@ -14,4 +14,4 @@ Error: Expected scalar element, not key-value.
|
2 | "single",
| ^~~~~~~~
Note: The collection is a set and not a record, because of this scalar value.
Note: The collection is a set and not a dict, because of this scalar value.

View file

@ -5,10 +5,10 @@
|
1 | [for kv in {"key": "value"}: kv]
| ^~
Error: Expected two variables in record iteration.
Error: Expected two variables in dict iteration.
--> stdin:1:11
|
1 | [for kv in {"key": "value"}: kv]
| ^~~~~~~~~~~~~~~~
Note: This is a record, it yields a key and value per iteration.
Note: This is a dict, it yields a key and value per iteration.

View file

@ -0,0 +1,5 @@
// This is an empty dict, not an empty set.
{}
# output:
{}

View file

@ -1,5 +0,0 @@
// This is an empty set, not an empty record.
{}
# output:
[]

View file

@ -3,14 +3,13 @@
## Near term
* [WIP] Colored output for json.
* Ensure `{}` is a dict, not a set, for json compatibility.
* [WIP] Update terminology; I am calling them dicts, not records.
* The ability to turn coloring on or off, respect <https://no-color.org/>.
* Add assertions.
* Absorb the `highlight` command into `fmt` and make it use the same coloring?
* Different output modes, RCL in addition to json (so we can preserve sets);
possibly yaml output.
* Preserve insertion order in dicts and sets.
* Update terminology; I am calling them dicts, not records.
## Method vs. field access

View file

@ -7,7 +7,7 @@
//! Evaluation turns ASTs into values.
use std::collections::{BTreeMap, BTreeSet};
use std::collections::BTreeMap;
use std::rc::Rc;
use crate::ast::{BinOp, Expr, FormatFragment, Seq, UnOp};
@ -23,8 +23,9 @@ pub fn eval(env: &mut Env, expr: &Expr) -> Result<Rc<Value>> {
eval_seq(env, seq, &mut out)?;
}
match out {
// If we have no keys, its a set.
SeqOut::SetOrDict => Ok(Rc::new(Value::Set(BTreeSet::new()))),
// If we have no keys, its a dict, because json has no sets,
// and `{}` is a json value that should evaluate to itself.
SeqOut::SetOrDict => Ok(Rc::new(Value::Map(BTreeMap::new()))),
SeqOut::Set(_, values) => {
let result = values.into_iter().collect();
Ok(Rc::new(Value::Set(result)))