Syntax Ambiguities & Parsing Complexity - Moving Forward #17715
Replies: 11 comments 33 replies
-
How about just $ {
if linux {
println('linux')
}
else if windows {
println('windows')
}
else {
println('other')
}
} Shorter syntax in most cases (though slightly longer for single $if or $for). |
Beta Was this translation helpful? Give feedback.
-
For arrays, I'd like to see #17514 :-) |
Beta Was this translation helpful? Give feedback.
-
And https://discord.com/channels/592103645835821068/592106336838352923/1084149368313090079 to get rid of _default. |
Beta Was this translation helpful? Give feedback.
-
Thanks for starting this topic, I added a couple of cents from myself, maybe I'll remember something else later. Ambiguity and other problemsGenericsGenerics and array accessstruct Foo {
funcs []fn ()
}
foo := Foo{
funcs: [fn() {
println('hello')
}]
}
index := 0
foo.funcs[index]()
// ^^^^^^^^^ array access or method call? and import datatypes
struct Foo {}
fn (f Foo) method[T]() {
println('method with ${T.name}')
}
foo := Foo{}
foo.method[datatypes.Stack[int]]()
// ^^^^^^^^^^^^^^^^^^^^^^^^ array access or method call? To solve this problem, the parser must be case-sensitive and assume that an identifier with a small However, if you use a fully qualified module name for a type, then the parser needs to look 2 tokens Generics and field attributesstruct Boo[T] {}
struct Foo[T] {
boo Boo[T]
// ^^^^^^ generic Boo
boo2 Boo [T]
// ^^^ ^^^ attribute
// just Boo
}
foo := Foo[int]{} The JSON decodef := json.decode(Foo, j) or { panic(err) }
// ^^^ type The presence of special functions, where the type is a parameter, greatly complicates parsing, and The
|
Beta Was this translation helpful? Give feedback.
-
Methods in structs look like this:
so, in case Generics why not do:
Applying this to the examples in the documentation:
and for a method:
BTW: this:
could also be a call of a function stored in a map (stored as voidptr). |
Beta Was this translation helpful? Give feedback.
-
Petr Makhnev escribió/skribis/wrote/scrit (2023-03-19T22:20:13-0700):
Now the `<<` operator is used to denote a left bit shift and as
operator for adding a new element to an array.
I would prefer this operator to be used only for bit shifting.
+1
That unrelated second usage of `<<` was suprising when I first saw it.
Reusing, say, the `+` operator as a statement would have a similar
effect on regularity and legibility.
…--
Marcos Cruz
http://programandala.net
|
Beta Was this translation helpful? Give feedback.
-
I would just ban
Capital letters for types is fine and should stay.
|
Beta Was this translation helpful? Give feedback.
-
|
Beta Was this translation helpful? Give feedback.
-
With the new attributes we can have something like
|
Beta Was this translation helpful? Give feedback.
-
Another point of note: If we are going to have aliases at all, they should always act like actual aliases. We have had too many problems where you couldn't use an operator or a method on an alias that was available on the original. This should never be the case. An alias should be exactly that... an alternative name for the same thing as the original. So all operators, all methods, etc., etc. should work exactly the same on the alias as it does on the original. The only difference between an alias and it's original besides the name that is typed (obviously) is any extra methods added to the alias would only be available on the alias, not the original. |
Beta Was this translation helpful? Give feedback.
-
A syntax ambiguity in strings... you can get the runes out of a string ( s += ` ` fails, while s += ` `.str() works. I think the first way should work, as well, and avoid the extra string conversion. |
Beta Was this translation helpful? Give feedback.
-
I have started this discussion as there are whispers of a compiler rewrite some time in the near future.
There are syntax issues which I feel need to be addressed before a rewrite occurs. They need to be addressed either way.
Please mention any ambiguities or syntax issues you know of which are not listed here so I can add them.
Attributes
Attributes work fine just about everywhere, but there are some cases where there are ambiguities.
The simplest fix for the issues below would be to change the attributes syntax, for example to:
@[attribute_a]
, which would allow the attribute syntax to remain the same everywhere without any special cases.The current suggested syntax change is:
OR
This change requires removing the
@keyword
feature, or changing it's syntax, for example to#keyword
.Struct Declaration field with fn type
You can see that
func_a fn() ! [attribute_a]
looks like the start of a fixed array result type. This can be parsed, but it adds a level of complexity which is not justified considering this issue can be removed completely.Struct Declaration field with default value
The cases above could be index expressions, or look like the start of one. There are ways to parse this and determine what is what, however its not ideal at all. Once again the complexity needed is not justified when this issue can be removed completely.
Struct Initialization in Condition Expression
These are a little tricky to parse, mostly
if StructA{} == StructA{} {
, I'm not sure what the solution for this could be. We may just need to deal with doing some trickery. I have listed it here anyway.Compile time If
This may ruffle some feathers.
It is the least important issue (if you can call it that) I have simply noted it here because it adds some unneeded parsing complexity, and possibly goes against syntax unification and separation of concerns.
I would like you to consider this statement/rule:
$
becomes compile time, for example a call$some_fn()
. This is nice and simple.Assuming the statement above is true, it doesn't make sense for
$
to find its way inside of the if expression itself and becomes a part of its branches. It seems out of the scope of the If expression (on a syntax level). Consider the simplicity of this AST:This is nit-picking on my behalf, however there is clarity to it.
So what I'm suggesting is to go from:
to this:
Index Expression vs Generic Call
It may seem like a difficult problem to determine the difference between an index expression and a generic call in some cases:
In actual fact the complexity to achieve this is very low. Parsing is simple, cases which can be determined in the parser will be, anything else will be determined after type checking. Since these are basic core features and the complexity of handling them is so low, I don't see any need to reconsider the syntax.
<<
Operator - Array push vs Left shiftThere is ambiguity as this operator has two uses, however the ambiguity only exists on a visual level, not a logical one. The complexity to parse and then later determine what operation we are doing is very low, although it must be done after type checking. We simply check the type of the left hand side expression, if we have an array then we know it's a push operation.
Beta Was this translation helpful? Give feedback.
All reactions