Skip to content

blakemcbride/Dynace-RS

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Dynace-RS — Dynamic Object System for Rust

Dynace-RS is a Rust crate family that adds a Dynace-/Smalltalk-style dynamic object system on top of Rust, including:

  • full object-oriented capabilities, including
    • classes, instances, methods, & generic functions
    • encapsulation
    • polymorphism
    • inheritance (single and multiple, with C3 linearization)
  • fully meta-class based (like Smalltalk)
  • dynamic binding and dispatching through generic functions (like CLOS)
  • class variables shared across the class hierarchy (Smalltalk semantics)
  • full reflection of classes, metaclasses, variables, methods, and generics
  • an automatic code generator that scans your crate and emits one typed Rust wrapper per generic, so callers write Area(&mut world, obj, &[]) rather than world.call_generic(GenericId::from_static("Area"), …)

Dynace-RS:

  • written in pure stable Rust (1.80+)
  • normal user code refers to classes by Rust marker types, not strings — typos are compile-time errors
  • macros (class!, method!, register!) hide the runtime plumbing behind a small, readable surface
  • twelve self-contained example crates progressing from a one-class "hello, object" to a multiple-inheritance shape system
  • full tutorial and reference manual in Texinfo, building to both HTML and PDF
  • cargo test keeps the runtime, macros, generator, and examples honest — 103 tests across the workspace, zero warnings

This is a Rust port of the long-running C system

Dynace-RS is a copy of the ideas from Dynace, a portable open-source extension to the C language that adds an object-oriented runtime with classes, generic functions, multiple inheritance, garbage collection, and threads. The original Dynace was fine-tuned over many years of commercial use; this crate brings the same object model into Rust, replacing the C preprocessor magic with proc macros and bolting onto the Rust type system wherever it makes sense.

Concepts that carry over directly: every entity is an object; classes and instances share the same dispatch path; metaclasses parallel the class hierarchy; methods are private and the public interface is the set of generated generics. Concepts that change: there is no tracing GC (the World owns the heap); thread support is intentionally out of scope for the current version; the cargo build / cargo test workflow replaces the makefile-driven C build.

Where to learn more

Three layers of material, depending on how you like to read:

  • A hands-on tutorial. docs/dynace-tutorial.texi walks through the system in narrative order, one chapter per concept, with code that maps directly to the example crates below.
  • A reference manual. docs/dynace-manual.texi is the API-and-concept reference, with a full error catalogue and design-rationale appendix.
  • Twelve runnable example crates. Everything under examples/, each a self-contained Cargo crate with its own readme.txt. They progress from 01-hello-object to a multiple-inheritance shape system in 12-mini-shape-system. See the Examples section below for the full list.

The tutorial and manual are written in Texinfo; build them to HTML and PDF with make -C docs all. The example crates run individually with cargo run -p example-NN-name (and have per-directory Makefiles).

A taste

use dynace::{GenericId, ObjectClass, ObjectRef, Result, Value, World};

dynace::class! { class AnimalClass : ObjectClass {} }
dynace::class! { class DogClass    : AnimalClass {} }
dynace::class! { class CatClass    : AnimalClass {} }

dynace::method! {
    impl AnimalClass {
        fn Speak(_w: &mut World, _r: ObjectRef) -> Result<Value> {
            Ok(Value::from("some generic animal noise"))
        }
    }
    impl DogClass {
        fn Speak(_w: &mut World, _r: ObjectRef) -> Result<Value> {
            Ok(Value::from("woof"))
        }
    }
}

fn main() -> Result<()> {
    let mut world = World::new();
    dynace::register!(&mut world,
        AnimalClass,
        DogClass,
        CatClass,
        AnimalClass::Speak,
        DogClass::Speak,
    );

    let rex      = world.new_instance_typed::<DogClass>()?;
    let whiskers = world.new_instance_typed::<CatClass>()?;
    let speak    = GenericId::from_static("Speak");

    println!("Dog says: {:?}", world.call_generic(speak, rex,      &[])?);
    println!("Cat says: {:?}", world.call_generic(speak, whiskers, &[])?);
    Ok(())
}

The cat falls through AnimalClass's implementation because dispatch walks the class precedence list and the dog's override wins for any DogClass instance.

Crates

  • dynace — the runtime: the object heap, class/metaclass/method layer, generic dispatch, and reflection.
  • dynace-macrosclass!, method!, and register! procedural macros. Re-exported through dynace.
  • dynace-gen — the code generator: scans crate source, merges with optional TOML databases from upstream Dynace-RS systems, emits one typed wrapper per generic. Available as a library and as a CLI (dynace-gen).
  • dynace-build — a thin build-script helper around dynace-gen, designed for [build-dependencies].

Examples

Twelve self-contained example crates live under examples/. Each is a real Cargo crate with its own Cargo.toml, src/main.rs, Makefile (targets build / run / clean), and readme.txt. They progress from the simplest possible runtime use to the full macro + generator pipeline:

Directory Demonstrates
01-hello-object One class, one method, one dispatched call
02-define-a-class Class identity and class_of
03-instance-variables Per-instance state
04-class-variables Class-wide shared state
05-single-inheritance Inherited instance and class variables
06-multiple-inheritance Diamond, C3, is_kind_of
07-private-methods Method dispatch and override
08-class-side-methods Factory + class-wide counter (advanced)
09-polymorphism One generic, many class implementations
10-generated-generics build.rs + dynace-build + generated wrapper
11-reflection Full reflection dump (advanced)
12-mini-shape-system Capstone: MI + ivars + cvars + class-side New

Each example builds individually — they are not part of the default workspace build, so cloning the repo and running cargo build does not pull them in. Run one with

cargo run -p example-NN-name        # from the workspace root
# or
make -C examples/NN-name run        # from inside the example directory

Each example can also be copied to any directory on disk and built standalone after editing one dependency path in the example's Cargo.toml. The example's own readme.txt documents that workflow.

Documentation

Two book-length documents live under docs/:

  • Tutorialdocs/dynace-tutorial.texi. A progressive hands-on guide that mirrors the example progression. Read this front-to-back if you are new to the system.
  • User manualdocs/dynace-manual.texi. The reference, organized by concept, with a full API surface, error catalogue, and design-rationale appendix. Read this when you know what you're looking for.

Both are Texinfo sources that build to HTML and PDF via the standard GNU toolchain:

make -C docs html      # → docs/build/html/{dynace-tutorial,dynace-manual}/index.html
make -C docs pdf       # → docs/build/pdf/{dynace-tutorial,dynace-manual}.pdf
make -C docs all       # both
make -C docs clean

(requires texinfo and a TeX distribution such as texlive-scheme-basic).

Dynace-RS_design.md at the repository root is the authoritative design document — the precise specification of every API, every error, and every invariant. Useful as a third reading after the tutorial and the manual.

Build & test

A top-level Makefile wraps the two underlying build systems (Cargo for the Rust crates, Texinfo for the docs):

make build     # build the four library crates
make test      # run the full test suite (103 tests)
make docs      # build HTML + PDF copies of the tutorial and manual
make all       # build + docs
make clean     # wipe everything generated (target/ and docs/build/)

Equivalent direct commands:

cargo build                            # → make build
cargo test                             # → make test
make -C docs all                       # → make docs
cargo clean && make -C docs clean      # → make clean

cargo run -p example-01-hello-object   # run a specific example
make -C examples/01-hello-object run   # same thing, from inside the example

The workspace's default-members list excludes the examples, so neither make build / cargo build nor make test / cargo test ever compile example code. Each example builds only when you name it explicitly with -p, or from inside its own directory.

License

Released under the BSD 2-Clause license — same terms as the original Dynace. See LICENSE.txt for the full text.

Credits

The Dynace object system — the design itself, the object model, the generic-function dispatch, the shared-class-variable semantics, all of it — was conceived by Blake McBride and refined over many years of commercial use in C; see the original at github.com/blakemcbride/Dynace.

This Rust implementation — the dynace, dynace-macros, dynace-gen, and dynace-build crates, plus the twelve example crates and the Texinfo tutorial and reference manual under docs/ — was written by Claude Code, Anthropic's command-line agent, working from Blake's design specification (Dynace-RS_design.md).

Heritage

Dynace-RS reimplements the core ideas of Dynace in Rust. The original Dynace was used in production for over a decade; this Rust port preserves the object model (classes/metaclasses/generics, single + multiple inheritance, shared class variables, reflection) and the "methods are private, generics are public" discipline that makes Dynace-style systems pleasant to extend.

If you came here from the C Dynace and you're looking for the documentation that explains why the system is shaped this way, the Dynace user manual (PDF) is still the best starting point. The Rust manual under docs/ focuses on the Rust API surface.

Support

Commercial support is available from blake@mcbridemail.com.

About

Adds full object-oriented facilities to the RUST language

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors