Skip to content

Commit 000b030

Browse files
authored
Merge pull request #71 from Cakefish/object-terminology-rework
Object terminology rework
2 parents 967a486 + b2801a0 commit 000b030

13 files changed

Lines changed: 154 additions & 108 deletions

File tree

OVERVIEW.md

Lines changed: 67 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ In this way, Bauble is a format very useful for specifying information processed
55

66
Once a context has been created, that context can then be used for parsing various Bauble source files and extracting the newly parsed data back as typed values that can be used to update the state of the program.
77

8-
# BaubleContext
8+
# `BaubleContext`
99

1010
[`BaubleContext`] is used to register various Bauble source files to parse information from, as well as maintaining a type registry where every known type to Bauble is provided.
1111
Through [`BaubleContext`], various separate Bauble source files are able to reference each other's objects.
@@ -52,34 +52,63 @@ Whether the conversion is successful depends on the implementation of the [`Baub
5252
In order to support all Bauble values being parsed and represented as a single type in Rust, using type erasure is a possibility, however it has to be manually implemented.
5353
For example, a single `ErasedBauble` type which can represent any type that implements `Bauble`, but has to be explicitly downcast to the concrete type sometime later at runtime (when the type is known).
5454

55-
## Bauble overview
55+
# Bauble overview
5656

57-
# Includes (use)
57+
## Includes (use)
5858

5959
All Bauble source files support the usage of `use`.
6060
Similar to Rust, it may include any item defined from a separate Bauble module, as long as both modules (the module being used, and the module using) exist within the same [`BaubleContext`].
6161
Alternatively to `use`, like in Rust, the fully qualified path may be written out instead.
6262
`use` may be used to include both objects and Bauble registered types/traits.
6363

64-
# Object
64+
## Object
6565

6666
All bauble source files consists of a set of objets.
6767
A single Bauble object is a tree of Bauble values and a type.
6868
A Bauble object can be thought of as a single asset, being tied to a unique path.
6969
Objects are the format of its contents Bauble provides after it has parsed all of its files, and ultimately what is used to convery the parsed Bauble contents.
7070

71-
# Values
71+
### Object terminology
7272

73-
A value in Bauble is typed, and contains an enum representing the kind of the value (whether it is a number, a string, an array or a map for example).
73+
There are three kinds of Bauble objects. Top level, local, and inline. These can be seen
74+
represented in the [`ObjectPath`] enum.
75+
76+
A top level (or Top for short) object is the main kind of object. A single source file has a single
77+
top level object which appears at the start of the file with the `0` identifier used as its name
78+
(NOTE: completely empty files are also allowed). These objects have the same path as their
79+
containing file. Top objects can be freely referenced by objects in other files. They can also be
80+
referenced in the current file both by their full path and by the special `0` identifier.
81+
82+
Local objects are the remaining named objects in a file that appear after the top object. They can
83+
only be referenced by other objects in the same file and only via their name rather than a full
84+
path.
85+
86+
An inline object is a reference value within a Bauble object which is not written as a reference in
87+
the source (see [References](#references)). Instead they appear as an "inlined" object directly
88+
defined together with the object. Functionally, inline objects work similar to a regular reference
89+
with the difference being they are defined locally to the object where they are used and are not
90+
named separately referencable objects themselves. They act as a convenience for the alternative of
91+
defining and referencing a separate object. The paths of these objects are generated based on the
92+
parent object when loading a Bauble file.
93+
94+
In addition to referencing other Bauble objects, external assets can be referenced. These are
95+
assets that aren't bauble files. For example, an audio or image asset. They can be exposed to be
96+
referenced by bauble values via `BaubleContext::register_asset`. When an object references an
97+
external asset it uses `ObjectPath::Top` wrapping the path provided to `register_asset `. When
98+
something can be either a Bauble object or an external asset, we use the term "asset".
99+
100+
## Values
101+
102+
A value in Bauble is typed, and contains an enum representing the kind of the value (whether it is a number, a string, an array or a map for example).
74103
Values are not that usually interacted with by the end user, as generally Bauble is implemented through the derive macro which means the user does not need to handle parsing from a raw Bauble value themselves.
75104

76-
# Types
105+
## Types
77106

78107
Types are registered to the [`BaubleContext`] through the builder, and every type requires the [`Bauble`] trait to be implemented on top of it.
79108
The [`Bauble`] trait determines how the type gets registered into the [`BaubleContext`], how it is parsed from Bauble source, and what path the type has.
80109
In Bauble every object is associated with a type, the type may be explicitly written with the value or implied by context, similar to type inference rules in Rust.
81110

82-
# Traits
111+
## Traits
83112

84113
Traits may be registered to Bauble in the form of `dyn Trait` types.
85114
If a trait has been registered, `dyn Trait` can then be used within registered Bauble types. In order for Bauble to parse a value of type `dyn Trait` with a value of a type that implements `Trait` called `T`, both `Trait` the `T` must be registered, and Bauble must know `T` implements `Trait`.
@@ -88,30 +117,42 @@ Bauble is unable to use reflection and figure out if a type implements a trait b
88117
In order to register Bauble traits, you can use the method [`get_or_register_trait`](types::TypeRegistry::get_or_register_trait), then in order to mark a type as implementing that trait in Bauble,
89118
use [`add_trait_dependency`](types::TypeRegistry::add_trait_dependency)
90119

91-
# Modules
120+
## Modules
121+
122+
Every registered source file in Bauble is a module, similar to Rust. Every module contains various objects. The notion of sub-modules are not really present in Bauble.
123+
124+
## Paths
92125

93-
Every registered source file in Bauble is a module, similar to Rust. Every module contains various assets. The notion of sub-modules are not really present in Bauble.
126+
Every asset, module, reference and registered type/trait in Bauble has a corresponding unique path.
127+
In Bauble this is known as [`path::TypePath`], and is the association to that particular element in
128+
the [`BaubleContext`].
129+
A path consists of various elements. Similar to Rust, most elements are seperated by `::`, so
130+
`a::b` means element `b` which is a child of element `a`.
131+
An element here can be a module, type, object, or external asset.
94132

95-
# Paths
133+
References to Objects use [`object_path::ObjectPath`] which is an enum that augments
134+
[`path::TypePath`] with information about the kind of object. Note, local and inline objects are
135+
not known to the `BaubleContext` so referring to top objects in the `BaubleContext` just uses
136+
`TypePath`.
96137

97-
Every asset, module, reference and registered type/trait in Bauble has a corresponding unique path. In Bauble this is known as [`path::TypePath`], and is the association to that particular element in the [`BaubleContext`].
98-
A path consists of various elements. Similar to Rust, most elements are seperated by `::`, so `a::b` means element `b` which is a child of element `a`.
99-
An element here can be a module, type or object.
100-
There are things known as sub-objects which may be appended to the path of a regular object, which are effectively children of the current object.
101-
A sub-object's path is denoted by `<path to parent>&$ty@$idx` where `$ty` is the index of the type of the sub-object and `$idx` is the index of the sub-object to the parent (the first sub-oject being 0, the second 1, the third 2, etc).
138+
There are objects known as inline objects which are effectively children of the current object.
139+
Their paths are constructed by appending to the name of a regular object to create a new object
140+
path with a different name that shares the same path prefix.
141+
An inline object's path is denoted by `<path to parent>&$ty@$num` where `$ty` ID of the type of the
142+
inline object and `$num` is an aribtrary number that distinguishes different inline objects with
143+
the same parent (usually starting at 0).
102144

103-
# References
145+
## References
104146

105-
A reference is a Bauble object which may not be present in the current module.
106-
A Bauble object's value may use a reference to avoid code duplication in the local file (referencing a previous object to use its values), or to reference the value of a Bauble object from a different file (module).
147+
A reference is a value that points to another Bauble object or a registered external asset.
148+
A Bauble object's value may use a reference to avoid code duplication in the local file
149+
(referencing a previous object to use its values), or to reference the value of a Bauble object
150+
from a different file (module).
107151
References are specified using a bauble `Path`.
108152

109-
Bauble does expose the builtin type for references, [`Ref`], which can be used for convenience to represent references from Bauble in Rust.
110-
It is not required to use this type to represent references, custom types which are capable of parsing reference values are equal to the builtin [`Ref`] type, it is just a convenience.
153+
Bauble does expose the builtin type for references, [`Ref`], which can be used for convenience to
154+
represent references from Bauble in Rust.
155+
It is not required to use this type to represent references, custom types which are capable of
156+
parsing reference values are equal to the builtin [`Ref`] type, it is just a convenience.
111157

112-
# Sub-objects
113158

114-
A single Bauble object may contain sub-objects.
115-
A sub-object is a reference value within a Bauble object which is not written as a reference, and rather as an "inlined" object directly defined together with the object.
116-
Functionally sub-objects work similar to a regular reference with the difference being they are defined locally to the object where they are used and are not
117-
top level objects themselves.

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ Bauble has three steps in parsing.
1111

1212
## Examples of bauble
1313
```rust
14-
// bauble has the capability to use different types. Which are resolved by the `AssetCtx`
14+
// bauble has the capability to use different types. Which are resolved by the `BaubleContext`
1515
use rpg::{Enemy, DamageType};
1616

1717
slime = Enemy {

bauble/src/context.rs

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -133,9 +133,9 @@ impl BaubleContextBuilder {
133133
}
134134

135135
#[allow(missing_docs)]
136-
pub fn set_top_level_trait_requirement<T: ?Sized + BaubleTrait>(&mut self) -> &mut Self {
136+
pub fn set_object_trait_requirement<T: ?Sized + BaubleTrait>(&mut self) -> &mut Self {
137137
let tr = self.registry.get_or_register_trait::<T>();
138-
self.registry.set_top_level_trait_dependency(tr);
138+
self.registry.set_object_trait_dependency(tr);
139139

140140
self
141141
}
@@ -390,7 +390,7 @@ impl CtxNode {
390390
!node.is_empty()
391391
});
392392

393-
// Top level assets match the path of their file (and all assets registered in
393+
// Top level objects match the path of their file (and all objects registered in
394394
// BaubleContext are top level).
395395
self.reference.asset.take();
396396
}
@@ -605,27 +605,27 @@ impl BaubleContext {
605605

606606
let mut early_ctx = crate::value::EarlyContext::new(self);
607607

608-
// Register assets paths from each successfully parsed file into the early context (before
608+
// Register object paths from each successfully parsed file into the early context (before
609609
// types are known).
610610
for (file, values) in file_values.iter() {
611611
// Need a partial borrow here.
612612
let (path, _) = early_ctx.ctx.file(*file);
613613
let path = path.to_owned();
614-
crate::value::pre_register_assets(&mut early_ctx, path.borrow(), values);
614+
crate::value::pre_register_objects(&mut early_ctx, path.borrow(), values);
615615
}
616616

617617
let mut local_ctx = crate::local_context::LocalContext::new();
618618

619619
let mut delayed = Vec::new();
620620
let mut skip = Vec::new();
621621

622-
// Then, register assets from each successfully parsed file into the context (while
622+
// Then, register objects from each successfully parsed file into the context (while
623623
// resolving types).
624624
for (file, values) in file_values.iter() {
625625
// Need a partial borrow here.
626626
let (path, _) = early_ctx.ctx.file(*file);
627627
let path = path.to_owned();
628-
match crate::value::register_assets(
628+
match crate::value::register_objects(
629629
&mut early_ctx,
630630
&mut local_ctx,
631631
path.borrow(),
@@ -774,8 +774,9 @@ impl BaubleContext {
774774

775775
/// Get all the assets starting from `path`, with an optional maximum depth of `max_depth`.
776776
///
777-
/// Inline objects are not registered as assets, they are exclusively visible in the list of
778-
/// objects returned when loading/reloading files.
777+
/// Only top level objects are registered as assets (in addition to external assets that are
778+
/// manually registered for referencing by Bauble objects). Local and inline objects are
779+
/// exclusively visible in the list of objects returned when loading/reloading files.
779780
pub fn assets(
780781
&self,
781782
path: TypePath<&str>,

bauble/src/object_path.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
//! Bauble objects can either be top-level, local, or inline.
1+
//! Bauble objects can either be top level, local, or inline.
22
//!
33
//! For a reference to an object, this is known once the full path to an
44
//! object is resolved during value loading. That resolved path is represented using
@@ -14,8 +14,8 @@
1414
use crate::types::path::TypePath;
1515
use std::hash::{Hash, Hasher};
1616

17-
/// Special cased identifier that is required and only allowed for the first asset in a file
18-
/// (i.e. the top level asset that is named after the file).
17+
/// Special cased identifier that is required and only allowed for the first object in a file
18+
/// (i.e. the top level object that is named after the file).
1919
pub const TOP_LEVEL_IDENTIFIER: &str = "0";
2020

2121
/// Full path to a bauble object (or external asset). See [the module level documentation](self)
@@ -39,7 +39,7 @@ pub const TOP_LEVEL_IDENTIFIER: &str = "0";
3939
/// - `inline_ref` will be `ObjectPath::Inline("my_file::inline_ref&6@0")
4040
#[derive(Copy, Clone, Debug)]
4141
pub enum ObjectPath<S = String> {
42-
/// Top-level object or external asset. There is at most one per file.
42+
/// Top level object or external asset. There is at most one per file.
4343
///
4444
/// This shares the path of the containing file and uses the special identifier
4545
/// [`TOP_LEVEL_IDENTIFIER`].

bauble/src/parse/value.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -179,14 +179,14 @@ pub struct Binding {
179179

180180
#[derive(Debug, PartialEq, Eq, Hash)]
181181
pub enum BindingIdent {
182-
/// This is the top level asset in a parsed file.
182+
/// This is the top level object in a parsed file.
183183
///
184184
/// It has the special cased identifier `0` and appears as the first item in the file.
185185
///
186186
/// This holds no identifier string because it will have the same path as the file containing
187187
/// it.
188188
TopLevel(Spanned<()>),
189-
/// This is a local asset. I.e. any additional assets in a parsed file.
189+
/// This is a local object. I.e. any additional objects in a parsed file.
190190
Local(Ident),
191191
}
192192

bauble/src/types.rs

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ pub struct TypeRegistry {
115115
type_from_rust: HashMap<std::any::TypeId, TypeId>,
116116
to_be_assigned: HashSet<TypeId>,
117117

118-
top_level_trait_dependency: TraitId,
118+
object_trait_dependency: TraitId,
119119

120120
primitive_types: [TypeId; 5],
121121
}
@@ -269,8 +269,8 @@ impl TypeRegistry {
269269

270270
asset_refs: Default::default(),
271271

272-
// NOTE: Top level values always have to derive from this trait.
273-
top_level_trait_dependency: Self::any_trait(),
272+
// NOTE: Top level value in an object must always implement this trait.
273+
object_trait_dependency: Self::any_trait(),
274274

275275
to_be_assigned: Default::default(),
276276

@@ -304,14 +304,14 @@ impl TypeRegistry {
304304
this
305305
}
306306

307-
/// If a type implements the required top-level trait.
308-
pub fn impls_top_level_trait(&self, id: TypeId) -> bool {
309-
self.key_trait(self.top_level_trait_dependency).contains(id)
307+
/// If a type implements the required trait for all objects.
308+
pub fn impls_object_trait(&self, id: TypeId) -> bool {
309+
self.key_trait(self.object_trait_dependency).contains(id)
310310
}
311311

312-
/// The trait that's expected for all top-level bauble assets to have.
313-
pub fn top_level_trait(&self) -> TraitId {
314-
self.top_level_trait_dependency
312+
/// The trait that's expected for all bauble objects to have.
313+
pub fn object_trait(&self) -> TraitId {
314+
self.object_trait_dependency
315315
}
316316

317317
/// This is present in all `TypeRegistry`
@@ -574,7 +574,7 @@ impl TypeRegistry {
574574
// If the path is not writable then it cannot be validated
575575
// as it cannot be written out as Bauble source.
576576
|| !ty.meta.path.is_representable_type()
577-
|| !ty.meta.traits.contains(&self.top_level_trait_dependency)
577+
|| !ty.meta.traits.contains(&self.object_trait_dependency)
578578
{
579579
continue;
580580
}
@@ -607,8 +607,8 @@ impl TypeRegistry {
607607
// Check that instantiated objects match after being serialized to bauble text and
608608
// parsed.
609609
//
610-
// Changes in sub-asset paths are specifically ignored, only the content of the
611-
// sub-assets must match.
610+
// Changes in inline object paths are specifically ignored, only the content of the
611+
// inline objects must match.
612612

613613
// dummy top level object
614614
let mut source = "0 = ()\n".to_string();
@@ -772,9 +772,10 @@ impl TypeRegistry {
772772
}
773773
}
774774

775-
/// Sets the trait all top-level assets are expected to have. By default this is the any trait.
776-
pub fn set_top_level_trait_dependency(&mut self, tr: TraitId) {
777-
self.top_level_trait_dependency = tr;
775+
/// Sets the trait all types used for objects are expected to have. By default this is the any
776+
/// trait.
777+
pub fn set_object_trait_dependency(&mut self, tr: TraitId) {
778+
self.object_trait_dependency = tr;
778779
}
779780

780781
/// Registers `ty` as implementing `tr`.
@@ -1039,8 +1040,9 @@ pub type ValidationFunction =
10391040

10401041
/// Function that creates a instance of the default value. Stored in [`TypeMeta`].
10411042
///
1042-
/// * `&mut AdditionalUnspannedObjects` allows creating sub-assets if the new value needs to
1043-
/// reference sub-assets.
1043+
/// * `&mut AdditionalUnspannedObjects` allows creating objects if the new value needs to
1044+
/// reference additional objects (depending on configuration of the `AdditionalUnspannedObjects`
1045+
/// these can be created as inline objects or as new local objects).
10441046
/// * `&TypeRegistry` allows calling [`TypeRegistry::instantiate`] to create new default instances
10451047
/// of contained types and is used to get type information of contained types.
10461048
/// * `TypeId` is the ID of the type. This allows the function to retrieve information about the

0 commit comments

Comments
 (0)