zia/lib.rs
1// Library for the Zia programming language.
2// Copyright (C) 2018 to 2019 Charles Johnson
3//
4// This program is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8//
9// This program is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12// GNU General Public License for more details.
13//
14// You should have received a copy of the GNU General Public License
15// along with this program. If not, see <http://www.gnu.org/licenses/>.
16
17//! [](https://crates.io/crates/zia)
18//!
19//! # Interpreter for the Zia programming language
20//!
21//! The Zia project aims to develop a programming language that can be used to program itself.
22//! Instead of storing the source code as plain text and editing the raw text (which can easily break
23//! the program), the runtime environment of the interpreter (the `Context`) can be saved to disk and
24//! used in other programs. All the programming is done using an interactive shell such as
25//! [`IZia`](https://github.com/Charles-Johnson/zia_programming/tree/master/izia) or via an [online IDE](https://zia-lang.org).
26//! The commands sent are interpreted based on the `Context`. They are used to incrementally modify, test
27//! and debug the `Context`.
28//!
29//! Expressions for Zia commands represent a binary tree where parentheses group a pair of expressions
30//! and a space separates a pair of expressions. For example `"(ll lr) (rl rr)"` represents a perfect
31//! binary tree of height 2 with leaves `"ll"`, `"lr"`, `"rl"`, `"rr"` going from left to right.
32//!
33//! The leaves of the tree can be any unicode string without spaces or parentheses. These symbols may
34//! be recognised by the intepreter as concepts or if not used to label new concepts.
35//!
36//! Currently, only the lowest-level functionality has been implemented. It's important that programs
37//! are represented consistently and transparently within the `Context` in order to achieve a
38//! self-describing system. The syntax shown below may appear awkward but more convenient syntax will
39//! be possible once more functionality is added. For example, the need to group pairs of expressions
40//! in parentheses will be alleviated by functionality to set the relative precedence and associativity
41//! of concepts.
42//!
43//! So far there are 10 built-in concepts. A new `Context` labels these with the symbols, `"label_of"`,
44//! `"->"`, `":="`, `"let"`, `"true"`, `"false"`, `"assoc"`, `"right"`, `"left"`, "prec", "deafult", ">" but the labels
45//! can be changed to different symbols for different languages or disciplines.
46//!
47//! # Examples
48//!
49//! ```
50//! extern crate zia;
51//! use zia::{Context, ZiaError};
52//!
53//! // Construct a new `Context` using the `new` method
54//! let mut context = Context::new();
55//!
56//! // Specify operator precedence for `let` and `->`.
57//! assert_eq!(context.execute("let default > prec ->"), "");
58//! assert_eq!(context.execute("let (prec ->) > prec let"), "");
59//! // Cannot yet infer partial order. Requires implication to express transitive property
60//! assert_eq!(context.execute("let default > prec let"), "");
61//!
62//! // Specify the rule that the concept "a b" reduces to concept "c"
63//! assert_eq!(context.execute("let a b -> c"), "");
64//! assert_eq!(context.execute("a b"), "c");
65//!
66//! // Change the rule so that concept "a b" instead reduces to concept "d"
67//! assert_eq!(context.execute("let a b -> d"), "");
68//! assert_eq!(context.execute("a b"), "d");
69//!
70//! // Change the rule so "a b" doesn't reduce any further
71//! assert_eq!(context.execute("let a b -> a b"), "");
72//! assert_eq!(context.execute("a b"), "a b");
73//!
74//! // Try to specify a rule that already exists
75//! assert_eq!(context.execute("let a b -> a b"), ZiaError::RedundantReduction.to_string());
76//! assert_eq!(context.execute("let a b -> c"), "");
77//! assert_eq!(context.execute("let a b -> c"), ZiaError::RedundantReduction.to_string());
78//!
79//! // Relabel "label_of" to "표시"
80//! assert_eq!(context.execute("let 표시 := label_of"), "");
81//! assert_eq!(context.execute("표시 a b"), "\'c\'");
82//!
83//! // You can reduce a labelled concept
84//! assert_eq!(context.execute("let a -> d"), "");
85//!
86//! // Try to specify the composition of a concept in terms of itself
87//! assert_eq!(context.execute("let b := a b"), ZiaError::InfiniteDefinition.to_string());
88//!
89//! // Try to specify the reduction of concept in terms of itself
90//! assert_eq!(context.execute("let c d -> (c d) e"), ZiaError::ExpandingReduction.to_string());
91//!
92//! // Determine the truth of a reduction
93//! assert_eq!(context.execute("a -> d"), "true");
94//! assert_eq!(context.execute("d -> a"), "false");
95//!
96//! // A concept never reduces to itself
97//! assert_eq!(context.execute("a -> a"), "false");
98//!
99//! // Cannot reduce a reduction expression between unrelated concepts
100//! assert_eq!(context.execute("d -> f"), "d -> f");
101//!
102//! // Can ask whether a reduction is true or false
103//! assert_eq!(context.execute("(a -> d) -> true"), "true");
104//! assert_eq!(context.execute("(d -> a) -> false"), "true");
105//!
106//! // Let an arbitary symbol be true
107//! assert_eq!(context.execute("let g"), "");
108//! assert_eq!(context.execute("g"), "true");
109//!
110//! // Let an arbitary expression be true
111//! assert_eq!(context.execute("let h i j"), "");
112//! assert_eq!(context.execute("h i j"), "true");
113//!
114//! // Determine associativity of symbol
115//! assert_eq!(context.execute("assoc a"), "right");
116//!
117//! // Define patterns
118//! assert_eq!(context.execute("let _x_ and false -> false"), "");
119//! assert_eq!(context.execute("foo and false"), "false");
120//! ```
121
122#[macro_use]
123extern crate lazy_static;
124#[macro_use]
125extern crate maplit;
126#[cfg(not(target_arch = "wasm32"))]
127#[macro_use]
128extern crate slog;
129#[cfg(not(target_arch = "wasm32"))]
130extern crate slog_term;
131extern crate snafu;
132
133/// Abstract syntax tree. Relates syntax to concepts.
134mod ast;
135
136/// The units that make up the context. Defined in terms of their relationship with other concepts.
137mod concepts;
138
139/// Integers that represent concrete concepts.
140mod constants;
141
142/// The container of concepts that coordinates adding, reading, writing and removing of concepts.
143mod context;
144
145mod context_delta;
146
147mod context_search;
148
149/// The trait for describing incremental changes in state.
150mod delta;
151
152/// The errors that the users could make when making commands.
153mod errors;
154
155mod snap_shot;
156
157/// A container for adding, writing, reading and removing `Concept`s.
158pub use context::Context;
159
160pub use errors::ZiaError;
161
162// Saves having to construct a new `Context` each time.
163#[macro_export]
164lazy_static! {
165 pub static ref NEW_CONTEXT: Context = Context::new();
166}