Proposal: allow arbitrary compile-time code execution


(Steve Richey) #1

It is not uncommon to want to run code at build time. Xcode solves this need by allowing "Build Phases", which are often shell scripts which handle compile-time tasks.

It may be beneficial to Swift developers, especially those who are not programming on platforms supported by Xcode, to handle compile-time tasks in a powerful and expressive language with which they are already familiar: Swift!

In short, I propose the addition of a `#run` expression that allows the execution of code at compile time. This syntax and concept are borrowed from the programming language Jai (https://sites.google.com/site/jailanguageprimer/#TOC-Arbitrary-Compile-Time-Code-Execution) but the syntax fits nicely with other special expression syntax in Swift such as `#available`, `#selector`, `#file`, and so on.

Example:

func myFunction() -> String {
return "hello"
}

let myValue = #run myFunction()

At compile time, `myFunction` is evaluated and the result inlined to the `myValue` definition. At run time, `myValue` is a `String` containing `"hello"`.

This is useful for tasks that are relatively expensive to run but only need to be done once, such as lookup tables. Running the algorithm to generate those tables can be handled at compile-time, and the results retrieved at no cost at run time. Furthermore, this structure allows code reuse between the run time and build time code, obviating the need to perform similar tasks in, say, a Swift method and a Python script.

This is my first attempt at a Swift proposal, so any and all feedback is welcome! This seems like it should be easy enough to implement but I'm not especially familiar with Swift's internals. If there are any hurdles or unforeseen consequences associated with this from an implementation standpoint, that would be very useful to know.

Thank you for your time!

Best regards,
Steve Richey


(Jarod Long) #2

+1

I saw the Jai presentation that covered this feature, and it struck me as quite powerful. Simple compile-time asset processing is highly appealing to me -- that would be particularly helpful in the domain of games.

I think this feature has a very high value/complexity ratio.

Jarod

···

On Feb 7, 2016, at 20:29, Steve Richey via swift-evolution <swift-evolution@swift.org> wrote:

It is not uncommon to want to run code at build time. Xcode solves this need by allowing "Build Phases", which are often shell scripts which handle compile-time tasks.

It may be beneficial to Swift developers, especially those who are not programming on platforms supported by Xcode, to handle compile-time tasks in a powerful and expressive language with which they are already familiar: Swift!

In short, I propose the addition of a `#run` expression that allows the execution of code at compile time. This syntax and concept are borrowed from the programming language Jai (https://sites.google.com/site/jailanguageprimer/#TOC-Arbitrary-Compile-Time-Code-Execution) but the syntax fits nicely with other special expression syntax in Swift such as `#available`, `#selector`, `#file`, and so on.

Example:

func myFunction() -> String {
return "hello"
}

let myValue = #run myFunction()

At compile time, `myFunction` is evaluated and the result inlined to the `myValue` definition. At run time, `myValue` is a `String` containing `"hello"`.

This is useful for tasks that are relatively expensive to run but only need to be done once, such as lookup tables. Running the algorithm to generate those tables can be handled at compile-time, and the results retrieved at no cost at run time. Furthermore, this structure allows code reuse between the run time and build time code, obviating the need to perform similar tasks in, say, a Swift method and a Python script.

This is my first attempt at a Swift proposal, so any and all feedback is welcome! This seems like it should be easy enough to implement but I'm not especially familiar with Swift's internals. If there are any hurdles or unforeseen consequences associated with this from an implementation standpoint, that would be very useful to know.

Thank you for your time!

Best regards,
Steve Richey
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(David Sweeris) #3

I believe macro-ish stuff has been ruled "out of scope" until Swift 3 is out.

If not, it gets a +1 from me, and it'd serve as a nice stop-gap until Swift advances to the point that its own front-end can itself be written in Swift (at which point I *think* a bunch of very meta things involving the REPL and extensions become plausible — I think).

- Dave Sweeris

···

On Feb 7, 2016, at 20:29, Steve Richey via swift-evolution <swift-evolution@swift.org> wrote:

It is not uncommon to want to run code at build time. Xcode solves this need by allowing "Build Phases", which are often shell scripts which handle compile-time tasks.

It may be beneficial to Swift developers, especially those who are not programming on platforms supported by Xcode, to handle compile-time tasks in a powerful and expressive language with which they are already familiar: Swift!

In short, I propose the addition of a `#run` expression that allows the execution of code at compile time. This syntax and concept are borrowed from the programming language Jai (https://sites.google.com/site/jailanguageprimer/#TOC-Arbitrary-Compile-Time-Code-Execution) but the syntax fits nicely with other special expression syntax in Swift such as `#available`, `#selector`, `#file`, and so on.

Example:

func myFunction() -> String {
return "hello"
}

let myValue = #run myFunction()

At compile time, `myFunction` is evaluated and the result inlined to the `myValue` definition. At run time, `myValue` is a `String` containing `"hello"`.

This is useful for tasks that are relatively expensive to run but only need to be done once, such as lookup tables. Running the algorithm to generate those tables can be handled at compile-time, and the results retrieved at no cost at run time. Furthermore, this structure allows code reuse between the run time and build time code, obviating the need to perform similar tasks in, say, a Swift method and a Python script.

This is my first attempt at a Swift proposal, so any and all feedback is welcome! This seems like it should be easy enough to implement but I'm not especially familiar with Swift's internals. If there are any hurdles or unforeseen consequences associated with this from an implementation standpoint, that would be very useful to know.

Thank you for your time!

Best regards,
Steve Richey
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Félix Cloutier) #4

That's actually very complex for types that can't be serialized/"encoded".

Félix

···

Le 8 févr. 2016 à 00:12:17, Jarod Long via swift-evolution <swift-evolution@swift.org> a écrit :

+1

I saw the Jai presentation that covered this feature, and it struck me as quite powerful. Simple compile-time asset processing is highly appealing to me -- that would be particularly helpful in the domain of games.

I think this feature has a very high value/complexity ratio.

Jarod

On Feb 7, 2016, at 20:29, Steve Richey via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

It is not uncommon to want to run code at build time. Xcode solves this need by allowing "Build Phases", which are often shell scripts which handle compile-time tasks.

It may be beneficial to Swift developers, especially those who are not programming on platforms supported by Xcode, to handle compile-time tasks in a powerful and expressive language with which they are already familiar: Swift!

In short, I propose the addition of a `#run` expression that allows the execution of code at compile time. This syntax and concept are borrowed from the programming language Jai (https://sites.google.com/site/jailanguageprimer/#TOC-Arbitrary-Compile-Time-Code-Execution) but the syntax fits nicely with other special expression syntax in Swift such as `#available`, `#selector`, `#file`, and so on.

Example:

func myFunction() -> String {
return "hello"
}

let myValue = #run myFunction()

At compile time, `myFunction` is evaluated and the result inlined to the `myValue` definition. At run time, `myValue` is a `String` containing `"hello"`.

This is useful for tasks that are relatively expensive to run but only need to be done once, such as lookup tables. Running the algorithm to generate those tables can be handled at compile-time, and the results retrieved at no cost at run time. Furthermore, this structure allows code reuse between the run time and build time code, obviating the need to perform similar tasks in, say, a Swift method and a Python script.

This is my first attempt at a Swift proposal, so any and all feedback is welcome! This seems like it should be easy enough to implement but I'm not especially familiar with Swift's internals. If there are any hurdles or unforeseen consequences associated with this from an implementation standpoint, that would be very useful to know.

Thank you for your time!

Best regards,
Steve Richey
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Adrian Kashivskyy) #5

What if the function you're evaluating depends on code that hasn't been compiled yet?

func f() -> String {
    return g()
}

let value = #run f()

func g() -> String {
    return "foo"
}

Regards,
Adrian Kashivskyy
Senior iOS Developer at Netguru

···

Wiadomość napisana przez David Sweeris via swift-evolution <swift-evolution@swift.org> w dniu 08.02.2016, o godz. 06:31:

I believe macro-ish stuff has been ruled "out of scope" until Swift 3 is out.

If not, it gets a +1 from me, and it'd serve as a nice stop-gap until Swift advances to the point that its own front-end can itself be written in Swift (at which point I *think* a bunch of very meta things involving the REPL and extensions become plausible — I think).

- Dave Sweeris

On Feb 7, 2016, at 20:29, Steve Richey via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

It is not uncommon to want to run code at build time. Xcode solves this need by allowing "Build Phases", which are often shell scripts which handle compile-time tasks.

It may be beneficial to Swift developers, especially those who are not programming on platforms supported by Xcode, to handle compile-time tasks in a powerful and expressive language with which they are already familiar: Swift!

In short, I propose the addition of a `#run` expression that allows the execution of code at compile time. This syntax and concept are borrowed from the programming language Jai (https://sites.google.com/site/jailanguageprimer/#TOC-Arbitrary-Compile-Time-Code-Execution) but the syntax fits nicely with other special expression syntax in Swift such as `#available`, `#selector`, `#file`, and so on.

Example:

func myFunction() -> String {
return "hello"
}

let myValue = #run myFunction()

At compile time, `myFunction` is evaluated and the result inlined to the `myValue` definition. At run time, `myValue` is a `String` containing `"hello"`.

This is useful for tasks that are relatively expensive to run but only need to be done once, such as lookup tables. Running the algorithm to generate those tables can be handled at compile-time, and the results retrieved at no cost at run time. Furthermore, this structure allows code reuse between the run time and build time code, obviating the need to perform similar tasks in, say, a Swift method and a Python script.

This is my first attempt at a Swift proposal, so any and all feedback is welcome! This seems like it should be easy enough to implement but I'm not especially familiar with Swift's internals. If there are any hurdles or unforeseen consequences associated with this from an implementation standpoint, that would be very useful to know.

Thank you for your time!

Best regards,
Steve Richey
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Haravikk) #6

Do we actually need the #run attribute in this case? If the compiler can detect that myFunction() has a fixed return value, or is only ever called once etc., then could it not just optimise away the function call entirely?

For example:

  func powersOfTwo() -> [UIntMax] { // Return an array of the first 64 powers of two.
    var steps = (sizeof(UIntMax) * 8)
    var powers[UIntMax] = [];
    repeat {
      steps -= 1
      powers.append(UIntMax(1) << steps)
    } while (steps > 0)
    return powers
  }

  let powersOfTwoList = powersOfTwo()

Since powersOfTwo() is only ever used once, it can be computed into an array constant; the compiler might already do that, I’m not sure. The main difficulty is whether the compiler can detect code that has no predictable return value, e.g- a call that returns the current time, as this would prevent a function from being precomputed into a constant in this way. There may also be cases where a function’s precomputed value could be very large in which case it might be more desirable to compute it only as needed, though if powersOfTwoList were a static value this wouldn’t matter.

In other words, I think we should be clear on where macros will actually offer functionality that the compiler can’t provide for us, as it seems to me that in the examples given so far we could just use regular code and the compiler can factor it out for us, or we could have an attribute that allows us to indicate which code the compiler should try to factor out. But as a general rule I think if the compiler can factor out unnecessary functions itself, then this could be better in the long run for efficiency anyway, and that’s assuming it doesn’t already do this to some degree (hopefully someone can weigh in on that).

···

On 8 Feb 2016, at 04:29, Steve Richey via swift-evolution <swift-evolution@swift.org> wrote:

Example:

func myFunction() -> String {
return "hello"
}

let myValue = #run myFunction()

At compile time, `myFunction` is evaluated and the result inlined to the `myValue` definition. At run time, `myValue` is a `String` containing `"hello"`.

This is useful for tasks that are relatively expensive to run but only need to be done once, such as lookup tables. Running the algorithm to generate those tables can be handled at compile-time, and the results retrieved at no cost at run time. Furthermore, this structure allows code reuse between the run time and build time code, obviating the need to perform similar tasks in, say, a Swift method and a Python script.


(Chris Lattner) #7

Something like this would definitely be interesting to build out. We should investigate it post-Swift 3 in the context of a hygienic macro system.

-Chris

···

On Feb 7, 2016, at 8:29 PM, Steve Richey via swift-evolution <swift-evolution@swift.org> wrote:

It is not uncommon to want to run code at build time. Xcode solves this need by allowing "Build Phases", which are often shell scripts which handle compile-time tasks.

It may be beneficial to Swift developers, especially those who are not programming on platforms supported by Xcode, to handle compile-time tasks in a powerful and expressive language with which they are already familiar: Swift!

In short, I propose the addition of a `#run` expression that allows the execution of code at compile time. This syntax and concept are borrowed from the programming language Jai (https://sites.google.com/site/jailanguageprimer/#TOC-Arbitrary-Compile-Time-Code-Execution) but the syntax fits nicely with other special expression syntax in Swift such as `#available`, `#selector`, `#file`, and so on.


(Joe Groff) #8

This would be cool, but allowing arbitrary code from the enclosing context to be executed introduces difficult dependency ordering issues. I like the design of Metalua (http://metalua.luaforge.net), which allows for pretty explicit and flexible jumping up and down "meta" levels, which in addition to building values, can also build arbitrary ASTs. In Swift, that might look something like this:

// Compile-time available definitions, that produce Expr nodes
#{
func myCompileTimeFunction() -> Expr { ... }
}#

// Evaluate a compile-time function and expand the result expression here
let myValue = #(myFunction())

-Joe

···

On Feb 7, 2016, at 8:29 PM, Steve Richey via swift-evolution <swift-evolution@swift.org> wrote:

It is not uncommon to want to run code at build time. Xcode solves this need by allowing "Build Phases", which are often shell scripts which handle compile-time tasks.

It may be beneficial to Swift developers, especially those who are not programming on platforms supported by Xcode, to handle compile-time tasks in a powerful and expressive language with which they are already familiar: Swift!

In short, I propose the addition of a `#run` expression that allows the execution of code at compile time. This syntax and concept are borrowed from the programming language Jai (https://sites.google.com/site/jailanguageprimer/#TOC-Arbitrary-Compile-Time-Code-Execution) but the syntax fits nicely with other special expression syntax in Swift such as `#available`, `#selector`, `#file`, and so on.

Example:

func myFunction() -> String {
return "hello"
}

let myValue = #run myFunction()

At compile time, `myFunction` is evaluated and the result inlined to the `myValue` definition. At run time, `myValue` is a `String` containing `"hello"`.

This is useful for tasks that are relatively expensive to run but only need to be done once, such as lookup tables. Running the algorithm to generate those tables can be handled at compile-time, and the results retrieved at no cost at run time. Furthermore, this structure allows code reuse between the run time and build time code, obviating the need to perform similar tasks in, say, a Swift method and a Python script.

This is my first attempt at a Swift proposal, so any and all feedback is welcome! This seems like it should be easy enough to implement but I'm not especially familiar with Swift's internals. If there are any hurdles or unforeseen consequences associated with this from an implementation standpoint, that would be very useful to know.

Thank you for your time!

Best regards,
Steve Richey
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Wallacy) #9

I think this proposal follow the same principle of the Tail Call
Optimization keyword/attribute proposal. It's a "thing" with the compiler
can do alone, but can be "improved" with some user annotation.

The main question (for me) of this proposal, is: The idea is evaluate the
result of any runtime function, for the "next build"? Like Profile Guided
Optimization (PGO) do for code paths?

If is: How to handle with functions with call "external modules" functions,
there's no way to sure the result of this functions will be consistent; so
any technique to detect the need to reevaluate the result may fail. Is this
case, the developer need to "manually" clean the cache or similar to
recompute the result.

Like said, there alot of "market" to "pre compiled" things, like in games.

···

Em seg, 8 de fev de 2016 às 07:39, Haravikk via swift-evolution < swift-evolution@swift.org> escreveu:

On 8 Feb 2016, at 04:29, Steve Richey via swift-evolution < > swift-evolution@swift.org> wrote:

Example:

func myFunction() -> String {
return "hello"
}

let myValue = #run myFunction()

At compile time, `myFunction` is evaluated and the result inlined to the
`myValue` definition. At run time, `myValue` is a `String` containing
`"hello"`.

This is useful for tasks that are relatively expensive to run but only
need to be done once, such as lookup tables. Running the algorithm to
generate those tables can be handled at compile-time, and the results
retrieved at no cost at run time. Furthermore, this structure allows code
reuse between the run time and build time code, obviating the need to
perform similar tasks in, say, a Swift method and a Python script.

Do we actually need the #run attribute in this case? If the compiler can
detect that myFunction() has a fixed return value, or is only ever called
once etc., then could it not just optimise away the function call entirely?

For example:

func powersOfTwo() -> [UIntMax] { // Return an array of the first 64
powers of two.
var steps = (sizeof(UIntMax) * 8)
var powers[UIntMax] = [];
repeat {
steps -= 1
powers.append(UIntMax(1) << steps)
} while (steps > 0)
return powers
}

let powersOfTwoList = powersOfTwo()

Since powersOfTwo() is only ever used once, it can be computed into an
array constant; the compiler might already do that, I’m not sure. The main
difficulty is whether the compiler can detect code that has no predictable
return value, e.g- a call that returns the current time, as this would
prevent a function from being precomputed into a constant in this way.
There may also be cases where a function’s precomputed value could be very
large in which case it might be more desirable to compute it only as
needed, though if powersOfTwoList were a static value this wouldn’t matter.

In other words, I think we should be clear on where macros will actually
offer functionality that the compiler can’t provide for us, as it seems to
me that in the examples given so far we could just use regular code and the
compiler can factor it out for us, or we could have an attribute that
allows us to indicate which code the compiler should try to factor out. But
as a general rule I think if the compiler can factor out unnecessary
functions itself, then this could be better in the long run for efficiency
anyway, and that’s assuming it doesn’t already do this to some degree
(hopefully someone can weigh in on that).
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Steve Richey) #10

Based on the response, it seems like there's some interest, but the team wouldn't get to it until after Swift 3 at the earliest. Should I open a pull request to the swift-evolution repo to allow feedback and prevent duplicate proposals?

- Steve

···

From: <clattner@apple.com<mailto:clattner@apple.com>> on behalf of Chris Lattner <clattner@apple.com<mailto:clattner@apple.com>>
Date: Monday, February 8, 2016 at 1:13 PM
To: Steve Richey <srichey@gowithfloat.com<mailto:srichey@gowithfloat.com>>
Cc: "swift-evolution@swift.org<mailto:swift-evolution@swift.org>" <swift-evolution@swift.org<mailto:swift-evolution@swift.org>>
Subject: Re: [swift-evolution] Proposal: allow arbitrary compile-time code execution

On Feb 7, 2016, at 8:29 PM, Steve Richey via swift-evolution <swift-evolution@swift.org<mailto:swift-evolution@swift.org>> wrote:

It is not uncommon to want to run code at build time. Xcode solves this need by allowing "Build Phases", which are often shell scripts which handle compile-time tasks.

It may be beneficial to Swift developers, especially those who are not programming on platforms supported by Xcode, to handle compile-time tasks in a powerful and expressive language with which they are already familiar: Swift!

In short, I propose the addition of a `#run` expression that allows the execution of code at compile time. This syntax and concept are borrowed from the programming language Jai (https://sites.google.com/site/jailanguageprimer/#TOC-Arbitrary-Compile-Time-Code-Execution) but the syntax fits nicely with other special expression syntax in Swift such as `#available`, `#selector`, `#file`, and so on.

Something like this would definitely be interesting to build out. We should investigate it post-Swift 3 in the context of a hygienic macro system.

-Chris


(Haravikk) #11

It seems a bit like an all new syntax though; what about an attribute that places some extra requirements on the function that throws an error if it can’t be produced at compile time? Not sure what it should be called, but I was thinking something like:

  @compile_time func myFunction(foo:String) -> Expr { … }

If the function can’t be made available at compile time due to dependencies or runtime requirements or whatever, then it will generate an error, otherwise it will be compiled ahead of other functions, and will explicitly have a precomputed value.

The idea is that while the attribute explicitly tells the compiler to compile this function in advance, it doesn’t introduce a separate class of function or a kind of language within a language, and the function could even still be called at runtime as well with dynamic values for foo (rather than constant ones).

That said, I still think that ideally the compiler should do as much of this pre computation as it can, the difference here is that the attribute explicitly requires it, while another could explicitly prevent it (if you’re concerned about memory).

···

On 8 Feb 2016, at 19:58, Joe Groff via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

This would be cool, but allowing arbitrary code from the enclosing context to be executed introduces difficult dependency ordering issues. I like the design of Metalua (http://metalua.luaforge.net <http://metalua.luaforge.net/>), which allows for pretty explicit and flexible jumping up and down "meta" levels, which in addition to building values, can also build arbitrary ASTs. In Swift, that might look something like this:

// Compile-time available definitions, that produce Expr nodes
#{
func myCompileTimeFunction() -> Expr { ... }
}#

// Evaluate a compile-time function and expand the result expression here
let myValue = #(myFunction())

-Joe

On Feb 7, 2016, at 8:29 PM, Steve Richey via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

It is not uncommon to want to run code at build time. Xcode solves this need by allowing "Build Phases", which are often shell scripts which handle compile-time tasks.

It may be beneficial to Swift developers, especially those who are not programming on platforms supported by Xcode, to handle compile-time tasks in a powerful and expressive language with which they are already familiar: Swift!

In short, I propose the addition of a `#run` expression that allows the execution of code at compile time. This syntax and concept are borrowed from the programming language Jai (https://sites.google.com/site/jailanguageprimer/#TOC-Arbitrary-Compile-Time-Code-Execution) but the syntax fits nicely with other special expression syntax in Swift such as `#available`, `#selector`, `#file`, and so on.

Example:

func myFunction() -> String {
return "hello"
}

let myValue = #run myFunction()

At compile time, `myFunction` is evaluated and the result inlined to the `myValue` definition. At run time, `myValue` is a `String` containing `"hello"`.

This is useful for tasks that are relatively expensive to run but only need to be done once, such as lookup tables. Running the algorithm to generate those tables can be handled at compile-time, and the results retrieved at no cost at run time. Furthermore, this structure allows code reuse between the run time and build time code, obviating the need to perform similar tasks in, say, a Swift method and a Python script.

This is my first attempt at a Swift proposal, so any and all feedback is welcome! This seems like it should be easy enough to implement but I'm not especially familiar with Swift's internals. If there are any hurdles or unforeseen consequences associated with this from an implementation standpoint, that would be very useful to know.

Thank you for your time!

Best regards,
Steve Richey
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution


(Chris Lattner) #12

Based on the response, it seems like there's some interest, but the team wouldn't get to it until after Swift 3 at the earliest. Should I open a pull request to the swift-evolution repo to allow feedback and prevent duplicate proposals?

I don’t think that this makes sense. The proposals in the swift-evolution repo are required to have some informed discussion and debate in the community before a proposal can be accepted for further discussion. Until Swift 3 is out of the door, we can’t have that pre-discussion.

I’d suggest logging a ticket in bugs.swift.org to keep track of this, but it is also a well known area of exploration, so we probably don’t need to track it.

-Chris

···

On Feb 8, 2016, at 12:54 PM, Steve Richey <srichey@gowithfloat.com> wrote:

- Steve

From: <clattner@apple.com <mailto:clattner@apple.com>> on behalf of Chris Lattner <clattner@apple.com <mailto:clattner@apple.com>>
Date: Monday, February 8, 2016 at 1:13 PM
To: Steve Richey <srichey@gowithfloat.com <mailto:srichey@gowithfloat.com>>
Cc: "swift-evolution@swift.org <mailto:swift-evolution@swift.org>" <swift-evolution@swift.org <mailto:swift-evolution@swift.org>>
Subject: Re: [swift-evolution] Proposal: allow arbitrary compile-time code execution

On Feb 7, 2016, at 8:29 PM, Steve Richey via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

It is not uncommon to want to run code at build time. Xcode solves this need by allowing "Build Phases", which are often shell scripts which handle compile-time tasks.

It may be beneficial to Swift developers, especially those who are not programming on platforms supported by Xcode, to handle compile-time tasks in a powerful and expressive language with which they are already familiar: Swift!

In short, I propose the addition of a `#run` expression that allows the execution of code at compile time. This syntax and concept are borrowed from the programming language Jai (https://sites.google.com/site/jailanguageprimer/#TOC-Arbitrary-Compile-Time-Code-Execution) but the syntax fits nicely with other special expression syntax in Swift such as `#available`, `#selector`, `#file`, and so on.

Something like this would definitely be interesting to build out. We should investigate it post-Swift 3 in the context of a hygienic macro system.

-Chris


(David Sweeris) #13

If you’re asking the mailing list as a whole, I certainly won’t complain. I’m not “on the team” or anything, though…

- Dave Sweeris

···

On Feb 8, 2016, at 12:54, Steve Richey via swift-evolution <swift-evolution@swift.org> wrote:

Based on the response, it seems like there's some interest, but the team wouldn't get to it until after Swift 3 at the earliest. Should I open a pull request to the swift-evolution repo to allow feedback and prevent duplicate proposals?

- Steve

From: <clattner@apple.com <mailto:clattner@apple.com>> on behalf of Chris Lattner <clattner@apple.com <mailto:clattner@apple.com>>
Date: Monday, February 8, 2016 at 1:13 PM
To: Steve Richey <srichey@gowithfloat.com <mailto:srichey@gowithfloat.com>>
Cc: "swift-evolution@swift.org <mailto:swift-evolution@swift.org>" <swift-evolution@swift.org <mailto:swift-evolution@swift.org>>
Subject: Re: [swift-evolution] Proposal: allow arbitrary compile-time code execution

On Feb 7, 2016, at 8:29 PM, Steve Richey via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

It is not uncommon to want to run code at build time. Xcode solves this need by allowing "Build Phases", which are often shell scripts which handle compile-time tasks.

It may be beneficial to Swift developers, especially those who are not programming on platforms supported by Xcode, to handle compile-time tasks in a powerful and expressive language with which they are already familiar: Swift!

In short, I propose the addition of a `#run` expression that allows the execution of code at compile time. This syntax and concept are borrowed from the programming language Jai (https://sites.google.com/site/jailanguageprimer/#TOC-Arbitrary-Compile-Time-Code-Execution) but the syntax fits nicely with other special expression syntax in Swift such as `#available`, `#selector`, `#file`, and so on.

Something like this would definitely be interesting to build out. We should investigate it post-Swift 3 in the context of a hygienic macro system.

-Chris

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Matt Whiteside) #14

Or maybe

@constexpr func myFunction(foo:String) -> Expr {…}

Regardless of the syntax, it’s great to see that I’m not the only one interested in this.

-Matt

PS - Metalua looks fascinating.

···

On Feb 9, 2016, at 01:18, Haravikk via swift-evolution <swift-evolution@swift.org> wrote:

It seems a bit like an all new syntax though; what about an attribute that places some extra requirements on the function that throws an error if it can’t be produced at compile time? Not sure what it should be called, but I was thinking something like:

  @compile_time func myFunction(foo:String) -> Expr { … }

If the function can’t be made available at compile time due to dependencies or runtime requirements or whatever, then it will generate an error, otherwise it will be compiled ahead of other functions, and will explicitly have a precomputed value.

The idea is that while the attribute explicitly tells the compiler to compile this function in advance, it doesn’t introduce a separate class of function or a kind of language within a language, and the function could even still be called at runtime as well with dynamic values for foo (rather than constant ones).

That said, I still think that ideally the compiler should do as much of this pre computation as it can, the difference here is that the attribute explicitly requires it, while another could explicitly prevent it (if you’re concerned about memory).

On 8 Feb 2016, at 19:58, Joe Groff via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

This would be cool, but allowing arbitrary code from the enclosing context to be executed introduces difficult dependency ordering issues. I like the design of Metalua (http://metalua.luaforge.net <http://metalua.luaforge.net/>), which allows for pretty explicit and flexible jumping up and down "meta" levels, which in addition to building values, can also build arbitrary ASTs. In Swift, that might look something like this:

// Compile-time available definitions, that produce Expr nodes
#{
func myCompileTimeFunction() -> Expr { ... }
}#

// Evaluate a compile-time function and expand the result expression here
let myValue = #(myFunction())

-Joe

On Feb 7, 2016, at 8:29 PM, Steve Richey via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

It is not uncommon to want to run code at build time. Xcode solves this need by allowing "Build Phases", which are often shell scripts which handle compile-time tasks.

It may be beneficial to Swift developers, especially those who are not programming on platforms supported by Xcode, to handle compile-time tasks in a powerful and expressive language with which they are already familiar: Swift!

In short, I propose the addition of a `#run` expression that allows the execution of code at compile time. This syntax and concept are borrowed from the programming language Jai (https://sites.google.com/site/jailanguageprimer/#TOC-Arbitrary-Compile-Time-Code-Execution) but the syntax fits nicely with other special expression syntax in Swift such as `#available`, `#selector`, `#file`, and so on.

Example:

func myFunction() -> String {
return "hello"
}

let myValue = #run myFunction()

At compile time, `myFunction` is evaluated and the result inlined to the `myValue` definition. At run time, `myValue` is a `String` containing `"hello"`.

This is useful for tasks that are relatively expensive to run but only need to be done once, such as lookup tables. Running the algorithm to generate those tables can be handled at compile-time, and the results retrieved at no cost at run time. Furthermore, this structure allows code reuse between the run time and build time code, obviating the need to perform similar tasks in, say, a Swift method and a Python script.

This is my first attempt at a Swift proposal, so any and all feedback is welcome! This seems like it should be easy enough to implement but I'm not especially familiar with Swift's internals. If there are any hurdles or unforeseen consequences associated with this from an implementation standpoint, that would be very useful to know.

Thank you for your time!

Best regards,
Steve Richey
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution