From dd6de13f0ba5ccf1fbc1c288a650fff6b68faf3d Mon Sep 17 00:00:00 2001 From: "Ben L. Titzer" Date: Thu, 27 Jun 2024 12:33:42 -0400 Subject: [PATCH] [ideas] Add ideas for model classes --- doc/ideas/Model.v3 | 128 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 128 insertions(+) create mode 100644 doc/ideas/Model.v3 diff --git a/doc/ideas/Model.v3 b/doc/ideas/Model.v3 new file mode 100644 index 000000000..9ceae742a --- /dev/null +++ b/doc/ideas/Model.v3 @@ -0,0 +1,128 @@ +/* + * Ideas for programmable meta objects and meta classes. + * Instead of using the vague and slightly intimidating "meta" word, we'll use "model". + */ + +/* + * Example A: Vehicles. + * 1. Vehicles have models which describe the shape of their wheels. + * 2. Vehicles have object identity, but the only other distinguishing characteristics of a vehicle are its color and its model. + * 3. Cars are vehicles that have a number of doors, fixed by the model of car, that can be broken off doing stunts. + * 4. Motorcycles are two-wheeled vehicles may optionally have a windshield or a chopper configuration. + * 5. The wheel configuration of a vehicle is extremely often used, because roads only interface with wheels. + * 6. Assume cars and vehicles are allocated frequently, models less so. Optimize space usage. +*/ + +// Preliminaries: wheel configs and colors. +type WheelConfig { + case Unicycle; + case Bicycle; + case Tricycle; + case Quad; + case More(count: u7); +} +enum Color { + BLACK, RED, YELLOW, BLUE +} + +/* + * Option 1: new Virgil syntax for declaring a "model". + * The syntax is: + model MyClass.link { + class MyClass { ... } + } + * A /model/ is the "metaclass" of a class and syntactically has the class nested inside it. + * Every instance of the (inner) class has a reference to an instance of the model (outer) class that created it. + * The two occurrences of "MyClass" in the syntax must be the same valid identifier. + * The "link" name must be a valid identifier or the keyword "model". + * The (outer) model class is like a regular class when used by itself. It can extend another + class, have methods, be instantiated with "new", etc. It just has a special dotted name. + * The inner class "MyClass" has its name available at the top level. Its name is not + "MyClass.link.MyClass"--its "MyClass", because it is the common thing which is frequently written. + * The ".link" part of the model name also indicates the name of a field implicitly declared + in "MyClass" that will point to the enclosing "MyClass.link" instance. + * Instances of "MyClass" can only be allocated in the scope of "MyClass.link". + Their implicit "link" field will be initialized to point to the containing model instance, + which is guaranteed to be non-null and definitely initialized. +*/ + +// Option 1 defining a vehicle. +// A basic vehicle has a color and a model. We store the color directly in the car, but +// factor out the wheel config into the Vehicle.model. +// - vehicle.model points to instance of Vehicle.model, which can't be null +// => can be packed into single 64-bit object +model Vehicle.model(wheels: WheelConfig) { // "Vehicle.model" name lifted to top level + class Vehicle(color: Color) { // "Vehicle" name lifted to top level + def dup() -> Vehicle; // abstrat method to make a copy + } + // no methods here, which means no way to make a Vehicle directly. +} + +// Option 1: define a car, which is a subclass of vehicle. +// Cars are limited in that they always have a quad wheel config. +// Cars are special in that they also have doors. They start having a number of doors dictated by their model. +// Then cars can lose doors in stunts. We want cars to always have a Car.model that stores the number +// of doors cars are expected to start with. +// - Car has a {color} field and a new {doors} field. +// - object header points to an instance of Car.model, which can't be null +// => can be packed into a single 64-bit object +model Car.model(doors: u6) extends Vehicle.model(WheelConfig.Quad) { // "Car.model" name lifted to top level + class Car extends Vehicle { // "Car" name lifted to top level + def var doors: u6; + new(color: Color, doors) super(color) { } + + def dup() -> Car { return Car.new(color, doors); } // makes a copy + def doStunt(random: int -> int) -> this { + if (doors > 0 && random(6) == 0) doors--; // unlucky stunt busted off a door + } + } + // It's only legal to make a Car inside Car.model. + def make(color: Color) -> Car { + return Car.new(color, doors); + } +} + +// Option 1: define a motorcyle, which is a subclass of vehicle. +// Motorcycles are limited in that they always have a bicycle wheel config. +// Motorcycles are special in that they can have a windshield and might be a chopper. +// Motorcycles are not mutable, and they can't do stunts like cars. Motorcycles are +// also limited to Color.BLACK. +model Motorcycle.model(windshield: bool, chopper: bool) extends Vehicle.model(WheelConfig.Bicycle) { + class Motorcycle extends Vehicle(Color.BLACK) { // "Motorcycle" lifted to top level + def dup() -> Motorcycle { return Motorcycle.new(); } // makes a copy + } + // It's only legal to make a Motorcycle in a Motorcycle.model. + def make() -> Motorcycle { + return Motorcycle.new(); + } +} + +// Example usages of the above definitions. +def main() { + def v1 = Vehicle.new(); // ERROR: illegal outside model + + def m1 = Vehicle.model.new(WheelConfig.Bicycle); // create new model of vehicle + + def m2 = Car.model.new(4); // create new 4-door car model + def c1: Car = m2.make(Color.RED); // create new red car + assert(m2 == c1.model); // every car remembers its model + var r = c1.doStunt().doStunt(); // do two stunts in a row + + def m3 = JetCar.model.new(JetEngineDesign.TURBOFAN); // create a new jetcar model + def c1: Car = m3.make(Color.RED); // create a new jetcar, which is just a Car + + def m4 = Motorcyle.model.new(true, false); // create a new motorcycle model + def mc1 = m4.make(); // create a new motorcycle +} + +// This file has a secret jet engine project! +private enum JetEngineDesign { + TURBOFAN, AERO_SPIKE +} + +// Option 1: define a private JetCar.model, which is a special kind of model. +// JetCar models can only have 2 doors. +// Private means it cannot be named outside this file. +private model JetCar.model(jet: JetEngineDesign) extends Car.model(2) { + // JetCar instances are not special (i.e. no subclass of Car). Only the model is special. +}