> Le 2 déc. 2017 à 12:20, Chris Lattner via swift-evolution > <swift-evolution@swift.org> a écrit : > >> *At worst*, you invoke the tool from the command line to build the Swift >> module that corresponds to a given Python module. >> >> py2swift <pythonmodulename> >> >> We could absolutely introduce tooling hooks to make the compiler initiate >> that step. > > This would have to be integrated into the swift compiler to provide a usable > experience IMO, because otherwise it won’t work with Playgrounds.
I'm not sure if that's what Doug was aiming at, but I read it to mean we could add a new import syntax like this one: import py2swift("DogModule") Instead of looking for a module in the _module search path_, the compiler would run a command-line tool called `py2swift` found in an _import tool search path_. The tool generates the module on the fly before returning the module path to the compiler, who can then continue with compiling. In the case above, the `py2swift` script would receive "DogModule" as its argument, introspect the Python module, generate bindings, and output the path to the generated binding module for the Swift compiler to use. The generated code for the binding module could look like this: import PyRuntimeGlue final class Dog { private let pyVal: PyVal init(_ pyVal: PyVal) { self.pyVal = pyVal } init(_ name: String) { pyVal = pyRuntimeNew(class: "Dog", name) } func add_trick(_ trick: PyVal) { pyRuntimeCall(pyVal, "add_trick", trick) } } and below the import line the usage would be the same as in your proposal: import py2swift("DogModule") // auto-generate bindings module let dog = Dog("Brianna") dog.add_trick("Roll over") let dog2 = Dog(Kaylee").add_trick("snore") Except now `Dog` is a real type instead of a variable masquerading as a type, auto-completion will work the way you'd expect, and you'll get a compile-time error if there is no Python method with that name on that type. There's still one problem though: Python functions returning a Dog will actually return you something of type PyVal. That'll force you to rewrap the value into the right type everywhere. Example: let dog = Dog(owner.dog) dog.add_trick("snore") // Dog.add_trick gets called The binding generator could take the AnyObject approach and have the binding module insert extensions for all methods in addition to the type: import PyRuntimeGlue final class Dog { private let pyVal: PyVal init(_ pyVal: PyVal) { self.pyVal = pyVal } init(_ name: String) { pyVal = pyRuntimeNew(class: "Dog", name) } func add_trick(_ trick: PyVal) { pyRuntimeCall(pyVal, "add_trick", trick) } } extension PyVal { func add_trick(_ trick: PyVal) { pyRuntimeCall(pyVal, "add_trick", trick) } } and now you can do: let dog = owner.dog dog.add_trick("snore") // PyVal.add_trick gets called Does that makes sense? -- Michel Fortin https://michelf.ca _______________________________________________ swift-evolution mailing list swift-evolution@swift.org https://lists.swift.org/mailman/listinfo/swift-evolution