[swift-evolution] Dynamic Class/Struct Definition At Run Time

Ted F.A. van Gaalen tedvgiosdev at gmail.com
Tue Oct 11 08:15:15 CDT 2016


Dynamic Class/Struct Definition At Run Time 

At the time of this writing, 11 October 2016, it is not possible to define arbitrary 
classes, structs and maybe other entities dynamically at run time in Swift. 
I have some idea about it, expressed in this message.

Creating class and other types dynamically should be as simple and as easy to understand 
as possible, preferably with nearly the same style and syntax as the "regular" declarations,
 leaving things like "Meta""Type" T.Self etc. as transparent as possible. 
That should in this context be "under the hood", as it is also the case 
when defining static classes. 

I have constructed the following (hypothetical) example code,
 which serves as just a "thinking model", so to speak.

    // In this example we dynamically create and use 
    // an example class named "Monolith"
    // First, we declare an "empty dynamic class"
    // (a slot) at compile time, that is later defined at run time.
   
    dynamic class Monolith // defined later just this line.
    
    // Use a constructor that accepts 
    // a string which contains a class definition, 
    // exactly like one would define a class in Swift statically. 
    // with the exception that name of the class is not specified. 
    // It is replaced by placeholder, an underscore, because 
    // the class name itself is inferred when declaring it. 
    // Specifying the class name will throw an error.

    var classDefStr = 
            "class _ :SCNNode, AnInterface, AnotherInterface "+
            "{var l = 9.0; var h = 4.0; var  w = 1.0; "     +
            "var color = UIColor.blue;"                    + 
            "func volume() -> Double { return l * w * h} “ +
            aStringWithAdditionalComponentDefinitions + "}"

    // Of course, this class definition string can also be assembled
    // completely programatically, read from a file or database, etc. 
    
    func defMonolithClass()
    {
        do  // try to define a class, NOT an instance.
        {
            try Monolith = 
                Meta.defineClass(withString: classDefStr)
        }
        catch Meta.classDefinitionError
        {
            // handle a possible class dynamic compilation errors
            // e.g. syntax errors. symbols not found etc.  
        }
        catch Meta.classCreationConflict
        {
            // class cannot be redefined 
            // when instances of Monolith still exist.
            // This restriction is probably necessary.
            // Also, static classes defined at compile time
            // cannot be redefined
        }

        // After successfully declaring our dynamic class,
        // we can now add more features to it, like 
        // properties and dynamic extensions. (It is not
        // possible of course to add statically defined extensions
        // and protocols to a non-existing dynamic class at compile time.
        // neither is it possible to do this at run time.)
        
        do 
        {  
            try Meta.addPropertyTo(Monolith,"mass",    3.4)
            try Meta.addPropertyTo(Monolith,"physics", PhysicsBody)
            try Meta.addExtensionTo(Monolith, someExtensionDefStr)
        }
        catch Meta.classExtenderError
        {
            // handle the error
        }
        catch Meta.classCreationConflict
        {
            // class definition cannot be altered 
            // when instances of Monolith (still) exist.
            // This restriction seems to be necessary.
            // Also, static classes defined at compile time
            // cannot be extended dynamically. 
        }
    }
    
    ...

    defMonolithClass()
    
    // After having dynamically declared the example class,
    // we can produce instances of it, like with any 
    // other class. It throws an error
    // when the dynamic class has not been defined. 

    
    public let monolith = Monolith() 
    
    let vol = monolith.volume
    
    monolith = nil  // remove instance(s), pre ARC when we wish to 
                    // redefine it. 

    defMonolithClass()  // redefine it, possibly with other definition parameters as in the first definition in this example.

   

Some examples for additional functionality

let Bird: DynamicClass?


Bird = Meta.defineClass(withString: classDefStr)

Bird = Meta.defineClass(superClass: StaticClass | DynamicClass,
                        interfaces: [Protocol],
                  definitionString: classItemsDefStr)

Bird = Meta.defineCopyOfClass(class: StaticClass| DynamicClass,
                              append: classItemsDefString)



Meta.addpropertyTo(Monolith, 
                   name:"mass",initializeWith: 3.4, type: Float) 

Meta.addPropertyTo(Monolith,
                name "Person",initializeWith: someValue, type: Inferred) 

Meta.addConstantPropertyTo(Monolith,
                name "cow",initializeWithString: aString, 
                type: FourLeggedAnimal) 




In principle, variants of this could be used to define structs as well.

While Swift is mainly a statically typed language, recompilation or additional 
compilation and somehow link it al together is obviously necessary at run time, 
each time a dynamic structure is defined. 
Because of this, it will most probably have performance drawbacks 
at run time, but there are applications where that is acceptable.
Also, there many applications where dynamic entities are not needed, 
and therefore relying only on statically defined objects, which run as fast as usual.

I haven't thought (yet) very much about possible side effects and conflicts. 
One of the restrictions probably is that one cannot or should not, alter the 
class definition (hierarchy) as long as instances of it exist.
  
How to implement this and can it be done? I know almost nothing about 
compiler design and construction I assume that it is very complicated, 
but if it can be done it would be great, making Swift even more powerful 
than it already is. 

Interesting? 
Of course, there might be better ways to do this, it's just a (my) start of thinking.
Highly appreciate in feedback about this.

This currently is not in a time frame or meant as base for a proposal,


Kind Regards
Tedvg

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20161011/f9a59d77/attachment.html>


More information about the swift-evolution mailing list