On Monday, 1 May 2017 at 12:35:11 UTC, Petar Kirov [ZombineDev] wrote:
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.


Oh I agree. For text to text (or lambda to text) this is comprehensible and not too difficult (perhaps even simple with Dmitry Olshansky's Pry) but SPIRV is rather complicated, as evidenced by a 203 page spec *(that doesn't even include the OpenCL or Vulkan specific stuff). Having said that it shouldn't be too difficult to port the tablegen tables I've been working on for LLVM to D (or write a D backend for tablegen) and get most of the really boring work out of the way. I won't stop you, but just letting you know the rabbit hole is quite deep :)

The good news is the the runtime stuff will be all transferable.
This approach for SPIRV won't automatically translate for NVPTX like it will for ldc though, which is one of the main draws for dcompute

*Other languages probably have longer specs, but this is just for the format.

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

Reply via email to