Open qwertie opened 5 years ago
A couple of other things to note about properties...
Since get
and set
are binary operators it is necessary to give an argument even if a body would be useless (e.g. in interfaces). I envision using _
to denote the lack of body; the same syntax could be used for function declarations if and only if the function body is also attached with an operator:
.interface IListSource!T {
Count: T get _
TryGet(index:int): Maybe!T => _
Item[index:int]: T get _ // indexer
}
If the getter returns a lambda, the setter will be improperly embedded within the getter body:
LazyValue: T
| get () => LoadValue()
| set {...code}
This of course is parsed like (LazyValue: T) get ( () => ( LoadValue() set {...code} ) )
and presumably the user - who has no idea there is a weird parse going on - will be baffled if his code doesn't work. The compiler could perhaps detect the lambda (or the presence of other lowercase keyword operators which could also cause trouble) and ask the user to place the contents of the get
clause in parentheses or braces.
The other day I was thinking it would be nice to have a language that supports shorthand operators for public
/export
, private
, virtual
etc...
Foo() => {} // default accessibility (package?)
++Foo() => {} // public
+Foo() => {} // internal
*Foo() => {} // protected
+*Foo() => {} // protected | internal
-*Foo() => {} // protected & internal (private protected in C#)
-Foo() => {} // private
^Foo() => {} // virtual
^^Foo() => {} // override
^^^Foo() => {} // sealed override
%Foo() => () // umm... let's say static/singleton
But this would be a lot to remember and wouldn't work on get
and set
operators. Something that could work as a shorthand is a way of applying modifiers to multiple members:
@public @virtual @CustomAttribute {
Func1() => { }
Func2() => { }
Foo: int get _foo @private set _foo = value
}
I dunno, any thoughts on this @jonathanvdc? One could also argue that we ought to have keywords on all members anyhow, to aid grepping - I'd particularly like a keyword on member variables which I think tend to be more important to keep track of, and find, than functions (even though langs are more likely to have keyword for the latter). In any case I'd like LES to offer as much flexibility as practical to DSL/compiler authors.
I've been looking for a good way to represent properties in LES. There are some straightforward choices that can be used already:
But these styles (except the last) require a keyword to introduce them (
.prop
). I guess this wouldn't be too burdensome since you might want a keyword to indicate accessibility anyway...But fields and functions can be supported without a keyword, which creates an asymmetry:
So I was thinking about whether there is a way around this, and I thought of a nicely compact syntax:
(maybe too compact? well, I'm fine with it)
It would work for events too (though I'm inclined to insist on a keyword for that case):
Then I noticed a problem - since
get
andset
are ordinary binary operators, there is no obvious way to associate attributes with them. So how do we represent the classic case of a public getter with private setter (or the more taboo sealed getter and virtual setter)?Well... we could technically allow attributes that annotate the operators themselves...
In the syntax tree, the attributes would annotate the target (not the expression) as follows:
You could, of course, annotate any operator this way:
Currently, attributes are only allowed at the beginning of an expression. If operators can have attributes, then surely subexpressions ought to be allowed to have attributes too?
But then the question arises of how to decide how much of an expression the attribute would apply to. Perhaps an attribute can simply be associated with as much of an expression to its right as is logically possible according to the current precedence floor; in that case I believe the expression above would have the following structure.
I'm not entirely sold on either of these proposals, but it certainly seems worth exploring.