MichaelRFairhurst / wake-compiler

C++ compiler for the programming language Wake: a fast, expressive, typesafe language built with testability from the ground up.
https://cdn.rawgit.com/MichaelRFairhurst/wake-compiler/docs/index.html
MIT License
56 stars 7 forks source link

Anonymous function syntax #83

Closed MichaelRFairhurst closed 9 years ago

MichaelRFairhurst commented 9 years ago

Edit: Final proposed syntax is:

var comp = {Num, $Num -> return Num < $Num; };
var $comp = {a, b -> return a < b; };
var $$comp = {{T} T, $T -> return T < $T; };
Text[].sort({a, b -> return a < b; });

Its worth noting that Map and Tuple syntax may get restricted by this. Maps will either have to look something like M{a: b, c: d} or else we'll have to swap to either a GLR or a backtracking RD parser. Tuples can either be T{a, b} or, should we move to GLR/backtracking RD parser anyway, maybe we can do (a, b).

The rest is me talking at myself about some alternatives, left for historical reasons

Need to come up with an unambiguous syntax

for instance

(Text, Text) -> { }

is ambiguious up until the ,, since it could just be a var in parens, so that's out.

fn(Text, Text) -> { }

is potentially ambiguous until the '->' because it could just as easily end in

from myProvider;

but its technically still a fnType being parsed beforehand so it might work.

MichaelRFairhurst commented 9 years ago

This comment is me talking to myself/considering alternative syntaxes, and is left for historical reasons

Would be cool to do

fn a, b {...}

but this wouldn't support type parameters in the future..

fn{T from Writer} T, Num {...}

the problem is that we can't tell if the opening curly brace begins a fn with no args or the beginnings of a type parameter. We coould do the opposite

fn T, Num {...} {T from Writer}

but that's...obviously gross.

Maybe we can eventually sacrifice some unity in the language and go for a scala/swift approach.

 fn T, Num : T from Writer {...}

but this is actually also ambiguous... In fact... come to think of it

fn Writer {...}

is ambiguous...

So we need an opening and closing delimiter for the arguments.

fn(Writer) {...}

Which makes me with we could just do

(Writer) {...}

but that is not an LL(1) grammar..........Maybe in the future we could make the fn optional.

oooh maybe

fn a, Num -> {...}
fn -> {...}
fn {T from Writer} T, Num -> {...}

And maybe in the future we'd drop the need for 'fn ->' too, let '->' do the trick.

But it does lead me to wonder, why exactly is '->' supposed to be better than '(' and ')'?

fn(a, Num) {...}
fn(){...}
fn{T from Writer}(T, Num) {...}

Hmm...yknow, come to think of it, I think

{-> ...}
{a, Num -> ...}
{{T from Writer} T, Num -> ...}

is unambiguous..... It might look a bit weird here, but

var comp = {Num, $Num -> return Num < $Num; };
var $comp = {a, b -> return a < b; };
var $$comp = {{T} T, $T -> return T < $T; };
Text[].sort({a, b -> return a < b; });

Now the only problem I can think of is this combined with maps...

return {myVar.............

This is ambiguous. Of course, we have the option of abandoning an LL(1) grammar to do this. The expression is no longer ambiguous once we find a ':' or a '->'. Or adding a preceding delimiter like 'M{' or something.