1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
//! # General structure
//!
//! Nyandere is a *language*.
//! A language generally consists of:
//!
//! **Part** | **Description** | **Implementation**
//! ------------|------------------------------------------------|-------------------
//! *Alphabet* | The *building blocks* of structures/sentences. | [`syntax::lex`]
//! *Syntax* | How structures are *formed* and look like. | [`syntax`]
//! *Semantics* | What built structures *mean*. | Rest of this crate
//!
//! ## Why the distinction?
//!
//! In short, while syntax is concerned with accurately representing
//! the source code via types, it doesn't cover the actual meaning.
//! Semantics on the other hand encode what makes *sense*.
//! This is not automatically given.
//!
//! ### Example: Valid syntax, semantically meaningful
//!
//! ```text
//! create entity A # (1)
//! create entity B # (2)
//! balance from=A to=B # (3)
//! ```
//!
//! While `(1)` and `(2)` don't rely on past state, `(3)` does:
//! Entities `A` and `B` must exist for the command to be valid.
//! In the above case that is given: Both `A` and `B` exist and are entities.
//!
//! ### Example: Valid syntax, semantically nonsense
//!
//! ```text
//! balance from=C to=D # (4)
//! ```
//!
//! Neither entity `C` nor entity `D` exist!
//! Hence, while this is *syntactically* valid,
//! it is *semantically* invalid!
//! More concretely:
//! While [`syntax`] **is** able to encode `(4)`,
//! it is **not** possible to create a [`runtime::cmd`] of `(4)`
//! without having `C` and `D` defined first.[^1]
//!
//! [^1]: If you do find a way, that is a bug and should be fixed.
//!
//! # Pipeline
//!
//! The general processing pipeline is:
//!
//! 1. Load source code as a string.
//! 2. Parse string into a [`Script`] using [`syntax::parse`].
//! - [`Script`] serves as the AST root
//! 3. Run the [`Script`] in the [`Runtime`] using [`Runtime::run`]
//!
//! # Adding new commands
//!
//! Task list for adding a new command `nya`:
//!
//! ## 1. Syntax
//!
//! 1. Think of one (where is it used? what are its arguments?)
//! 2. Update `doc/syntax.abnf` appropriately
//! 3. Expand the AST in [`syntax::ast`]
//! to include `nya` below [`Stmt`][syntax::ast::Stmt]
//! in the tree
//! 4. Parse it in [`syntax::parse`]
//!
//! ## 2. Semantics
//!
//! 1. Add a submodule `nya` in [`runtime::cmd`] for the command
//! 2. In there, write a type `Nya` with the type-restricted fields for the command
//! 3. Implement [`runtime::cmd::Command`] for `Nya`
//!
//! ## 3. Testing
//!
//! Try to cover both edge cases and typical use cases.
extern crate macro_rules_attribute;
pub type Map<K, V> = BTreeMap;
pub type Set<T> = HashSet;
pub type Name = String;
pub type NameRef<'name> = &'name str;
use config;
pub use Runtime;
use ;
use Script;
/// Parses and runs the given script,
/// returning the final runtime state.