On Saturday, 29 April 2017 at 00:54:59 UTC, Nicholas Wilson wrote:
On Friday, 28 April 2017 at 13:31:33 UTC, Petar Kirov
[ZombineDev] wrote:
Other applications include:
* compiling/transpiling D functions to targets
like JS, SPIR-V,
I got you covered ;)
I know, and I'm looking forward to using your GPU support in LDC
:P
(LDC not CTFE though. It would be fiendishly complicated to do
at CTFE as a fair amount of compiler magic is necessary.)
The way I see it, metaprogramming is a whole spectrum. Yes, you
need a full compiler if you want to compile a whole program to
e.g. JS or WebAsm, but there are many areas where even the
smallest
improvement would be highly beneficial.
Take for example C#. It has zero CTFE capabilities (you can
safely ignore constant folding, which works only with string and
number literals),
yet it has pretty powerful reflection and code-generation
capabilities
at run-time. Even though the performance difference between CT
and RT
reflection is orders of magnitude, those reflection capabilities
are used
pervasively throughout the whole ecosystem. The prime example
being LINQ -
probably the most widely used feature of .NET. Given a chain of
operations
(similar to D's ranges) like:
dbContext.Persons
.Where(p => p.Birthdate < DateTime.Now.Date.AddYears(-18))
.Where(p => p.Birthdate > DateTime.Now.Date.AddYears(-28))
.Select(p => new { Name = p.FirstName + " " + p.LastName,
Birthdate = p.Birthdate })
It gets compiled to the following SQL:
-- Region Parameters
DECLARE @p0 DateTime = '1989-05-01 00:00:00.000'
DECLARE @p1 DateTime = '1999-05-01 00:00:00.000'
DECLARE @p2 NVarChar(1000) = ' '
-- EndRegion
SELECT ([t0].[FirstName] + @p2) + [t0].[LastName] AS [Name],
[t0].[Birthdate]
FROM [Person] AS [t0]
WHERE ([t0].[Birthdate] > @p0) AND ([t0].[Birthdate] < @p1)
As you can see the mapping and filtering is done entirely on the
database server side. The only magic need is to make the compiler
to
dump the AST. In C# that's accomplished by wrapping the function
type F in to an Expression<F> [0]. For example C#'s analog of:
InputRange!T filter(T)(InputRange!T source, bool delegate(T)
predicate)
is expressed as:
IEnumerable<T> Where<T>(IEnumerable<T> source, Func<T, bool>
predicate)
In order to request the AST of the predicate function, it needs to
be wrapped in Expression<T>:
IQueryable<T> Where<T>(
IQueryable<T> source, Expression<Func<T, bool>> predicate)
(IQueryable<T> [1] is an extension of IEnumerable<T> [2]
interface (which is
similar to D's Input/ForwardRange-s) which adds the Expression
property
which represents the AST of the query against the IQueryable data
source.)
----
In addition to compiling range operations to database queries,
this would
also be useful specializing on lambda's in range libraries (see
[3]) and
much more.
[0]:
https://msdn.microsoft.com/en-us/library/bb335710(v=vs.110).aspx
[1]:
https://msdn.microsoft.com/en-us/library/bb351562(v=vs.110).aspx
[2]:
https://msdn.microsoft.com/en-us/library/9eekhta0(v=vs.110).aspx
[3]: https://github.com/dlang/phobos/pull/4265