Architect

From SignalWiki

A Rust library for parsing a data serialization format of the same name to Rust, and for serializing data from Rust. Designed for IPC, human readability, and code reuse.

Design

Schema

Definitions for object types. Includes structs, enums, and tuple structs. Used to make IPC more efficient, for code generation, and for error checking.

Objects

Units of data, including built-in primitive types, structs, enums, and tuples. The latter three can be either anonymous or defined.

Modules

Separate schema and objects into namespaces. Usually based on files, but modules can be declared within files for finer control. File-level modules can be referenced by other modules.

Variables

These are module-level, named objects. They are intended to be referenced by anonymous objects or other

Syntax

Meta

  • mod <name> { <objects> }
Expression, defines a module block. Files are considered to be modules, named after their filename.
  • mod take(URL) [as <name>]
Expression, imports a module from the URL; optionally renaming it.
  • use <ident>(::<ident>)*(::\*)?
Imports identifiers and variables into the current scope. Asterisks import all identifiers and variables.
  • <expr>\[<expr>\]
Indexers copy objects from the referenced object by indexing into them. So, for example, foo["bar"] would take the object keyed "bar" from a hashmap variable named foo; lists and strings can also be indexed, using integers. Modules can also be indexed in the same way as a list; this copies objects from the module's DOM.
  • <expr>\[<expr>\]
Copies an object from a struct or tuple, similar to an indexer. If you want to evaluate the value of an ident and reference the field named after that value (instead of just referencing the field with that ident as its name), you must surround it with curly braces. Ex. foo.{bar} instead of foo.bar

Built-In Types

Primitives

()
bool
u8, 16, 32, 64, 128
i8, 16, 32, 64, 128
f32
f64
String

Structs & Enums

Vec<T>
HashMap<T: Eq + Hash, T>
Option<T>
(T, T, ...) // Anonymous tuples
{}

Schema

Structs & Tuple Structs

// Struct
struct <ident>\<generic type, ...\>[: <tag> + ...] {
  <ident>: <type> [! <default value>],
  ...
}
// Tuple Struct
struct <ident>\<generic type, ...\>[: <tag> + ...](<type> [! <default value>], ...);
// Unit Struct
struct <ident>[: <tag> + ...];

A unit struct is, functionally, just a tuple struct with zero fields.

Enums

enum <ident>\<generic type, ...\>[: <tag> + ...] {
  <struct def>,
  ...
}

Objects

Primitives

Same as Rust.

Vec

[a, b, c, ...]

Objects in an anonymous vec don't need to be the same type; this kind of Vec is typed as Vec<dyn>, which is translated to Rust as something like Vec<Box<dyn ArchObject>>.

HashMap

{ key: val, ... }

The key type must be tagged Eq + Hash. Most primitives, except floats, have these tags, and anonymous tuples inherit these if all of their fields are Eq + Hash.

Struct

<type> { <ident>: val, ... }

Structs can't be anonymous, because that would be indistinguishable from a hashmap.

Tuple

[<type>](val, ...)

Enum

[<enum type>::]<variant>[<definition block>]

Ex:

Option::Some(5)
None
Foo::Bar { Baz: 5 }

The enum type identifier is only necessary if the variant identifier hasn't been imported into the current scope.

Deserialization

Architect is designed to be deserialized directly into specific types, but it can also be deserialized into a generic DOM. In Rust, this is represented as:

struct Module {
  id: String,
  modules: HashMap<String, Module>,
  vars: HashMap<String, Object>,
  schema: HashMap<Type, Schema>,
  objects: Vec<Object>
}

See Also