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

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


thank you, Goffredo, Anton, see inline
TedvG
> On 11 Oct 2016, at 21:10, Goffredo Marocchi <panajev at gmail.com> wrote:
> 
> I quite like your builder pattern way of adding properties and methods :).
> 
> Sent from my iPhone
> 
> On 11 Oct 2016, at 19:40, Anton Zhilin via swift-evolution <swift-evolution at swift.org <mailto:swift-evolution at swift.org>> wrote:
> 
>> Hello Ted,
>> First of all, this topic belongs to reflection, which is specifically stated to be out of scope of Swift 4 Phase 1. So all considerations are purely theoretical for now.
>> 
The idea is not intended to be in a deadline/timeframe
could be Swift 7 for that :o) 
>> ..  That said, I also thought about this problem. The best I could imagine is something along the following lines:
>> 
>> var builder = StructBuilder(name: "Person")
>> builder.addProperty(name: "name", type: String.self)
>> builder.addProperty(name: "age", type: Int.self)
>> builder.addComputedProperty(name: "description", getter: { (this: Any) -> String in ... })
>> builder.addComformance(CustomStringConvertible.self)
>> let type: Any.Type = builder.build()
>> Obviously, to interact with such dynamic types and their objects, we need the whole working reflection system that we don’t have right now.
>> 
>> 
I don’t know how much reflection is needed in this context.
-Adding dynamic classes can be solved with incremental? recompiling 
based on previously generated compiler reference metadata, 
already present. (note that in debug mode there already is a lot of “reflection”
available)
 - static entities defined at the initial compilation
 - and cumulative for dynamic entities when additionaly compiled at run time.
As soon as a dynamically defined or redefined class (or struct) is compiled
it is then regarded as a static type, transparent to the application thus which instances 
cannot be dynamically altered, because they are “tied” to the class definition.
Instance creation is then the same as with statically defined classes

(but all this  is a bit simplified of course, and I don’t know much about compilers.
Maybe similar to Smalltalk where methods/classes are precompiled separately)

@ Chris: As a Compiler Pro could you say more about this and about the whole idea, Chris? 

Thanks
TedvG




>> 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/0ecb8547/attachment.html>


More information about the swift-evolution mailing list