# History of ada

• In the 70s, the USDoD was using over 400 programming languages
• This was probably too many
• Designed from 1977 to 1980
• First implemented completely in 1983
• Standardized in 1987, updated in 1995 and 2012
``````-- Ada
type My_Integer is new Integer;
type My_Integer is new Long_Integer;
type My_Integer is new Integer_32;
type My_Integer is new Integer range 10..9_999;
type My_Integer is range 10..9_999;

Foo: My_Integer;
Bar: Not_My_Integer;
Qux: Integer;

Foo := Foo + 1;  -- OK
Foo := Foo + Bar;  -- Not OK!
Foo := Foo + Qux;  -- Not OK!
Foo := Foo + Foo(Qux);  -- OK``````
``````// Rust
struct MyInteger(i32);
// below are hypothetical!
struct MyInteger(impl Int);
struct MyInteger(i32<10..10_000>);
struct MyInteger(impl Int<10..10_000>);

let foo: MyInteger;
let bar: NotMyInteger;
let qux: i32;

foo += 1;  // OK?
foo += bar;  // Not OK
foo += qux;  // OK?
foo += qux.into();  // OK``````

# ada vs rust

• Inheritance vs Composition
• Exceptions vs Result
• Dynamic checks vs Static Checks

# syn & quote

• Libraries for turning Rust tokens into an abstract syntax tree, and vice versa
• From dtolnay, maintainer of Serde
• Used by Serde and every other proc macro
• Without them, developing proc macros would be very, very painful
• Seriously don't even try it

# Proc Macros

• Rust's secret-est weapon
• Run arbitrary Rust code at compile-time to replace one token tree with any other token tree
• The "heavyweight" alternative to Rust's "lightweight" declarative macros
• Serde, Diesel, and Rocket all rely on this

# what even is a token tree

• Classical compiler architecture is described as a pipeline:                                                               Lexing Parsing Analysis Optimization Machine Code Generation
• Token trees are the intermediate step between lexing and parsing
• We can take as input any Rust code that passes the lexer, and output any Rust code
``````// Rust + procedural macros
struct MyInteger(i32);

#[range(10..10_000)]
struct MyInteger(i32);

#[range(10..10_000)]
struct MyInteger(impl Int);

#[range(1..10, 91..100)]
struct MyInteger(i32);

my_int += 1;  // OK
my_int += not_a_my_int;  // Not OK
my_int += some_i32;  // OK???
my_int += some_i32.into();  // OK``````

By bstrie

• 949