slint
slint copied to clipboard
Lookup of unqualified names and enums
Currently (as defined in lookup.rs) when we have a unqualified name in a expression (for example, right
in horizontal-alignment: right;
) the lookup rules goes as follow:
-
arguments of a callback (
bar
infoo(bar) => { /* ... */ }
) -
id of elements, including
self
,root
orparent
-
properties in the
self
element (example:background
is referring toself.background
- Scope lookup: for each element part of a
for
orif
construct: i. index or data (foo
oridx
infor foo[idx] in /* ... */
) ii. any properties in that element - properties in the
root
(eg,title
would likely be theroot.title
if the root is a Window) - A type, eg: a global or an enum (eg:
HorizontalAlignment
orSomeGlobal
) these are usually uppercase - If we are in an expression for a property on a enum type, or a callback that returns an enum type, any enum value (eg:
right
for thehorizontal-alignment
property would be the same asHorizontalAlignment.right
) - Likewise, for a expression of a property on a color, all the CSS color names are in scope
-
builtin functions (
min
,max
,rgb
,floor
,debug
, ...)
Now, there is the following things are not ideal:
A. Enum value in scope.
horizontal-alignment: right;
Works well, unless we add a right
property in the scope (which we actually want to add for the anchors)
To solve the problem we have the following options
α. Don't lookup the enum value at all and force user to always write
horizontal-alignment: HorizontalAlignment.right;
This is more verbose but at least we always know what it is and it is consistant (does not depends on the type of the property)
β. Move the enum lookup before property (but after id). We can still access the properties themselves by using the self.right
or root.right
if we want.
γ. Keep it as is, but then it is a breaking change to add a property of the same name of an enum value and is unfortinate for left
, right
, bottom
, top
The problem is the same with colours. should colours be considered as an enum anyway so we can do Color.blue
anyhere?
B. how to access builtin function if they are overriden by a property?
If there is a property max
in scope, it is not possible to call the max()
function anymore. We also want to add a property debug
to all elements. The option include
α. Do the lookup of functions before the lookup of properties
β. Add a way to get the function fully quallified... Std.max(..)
or .max(..)
or Global.max(..)
?
γ. Different lookup rules when there is a parentheses, so max
would be the property, but max(...)
would be the function. But what to do if it is a callback or if the property is callable?
C. Does it makes sense to have the properties of a repeater element in the scope?
I think we need to reconsider something regarding unqualified lookup: we want that adding properties to elements is not a breaking change. Same for enum values or types.
Also a piece of data: i added some debug to look for counts of what the unqualified lookup are:
printer demo (native): Stats { arg: 18, root: 84, root_explicit: 190, self_: 67, self_explicit: 10, parent: 54, id: 145, type_: 117, enum_: 54, model: 12, index: 14, scope: 0, function: 21, }
gallery(fluent) : Stats { arg: 30, root: 89, root_explicit: 218, self_: 114, self_explicit: 7, parent: 57, id: 156, type_: 129, enum_: 51, model: 3, index: 4, scope: 0, function: 24, },
(note that implicit self is counted as root within the root item itself)
So here is what i suggest should be the new lookup rules: (This assume, we will change the definition of the property so that we can no longer define property on inner elements (#191))
Start with local things:
- arguments of callback
- id of elements
- index or data of model (walk up the scopes)
-
local properties declared in the current component with
property
(what is currently usually inroot
) but walk up all scopes.
Global things:
- Type enum name or namespace, or global
- builtin functions
Type dependent
- enum values or CSS colors.
In particular, this proposal no longer resolve unqualified self.
base properties at all. Because having a lookup on self means that adding property in element would break if the user has used a declared property or a type.
According to the number, we query root properties more often, but actually we still often use self implicitly.
We could add the self properties in the list anyway: between 4. and 5. Because types usually starts with uppercase that might be ok, but we'd still have conflict with enum values. Unless we change our policy and put enum value in camelcase too.
We can also have another syntax to access self property. instead of self.foo
we could write .foo
or something like that.
We still have a possible conflict between type, builtin function and enum values when we allow user to declare their own enum value or if we want to add a builtin function that overlap with an enum value. We might want to reorder 7. and 8. but that is also problematic.
Maybe we could also make it more robust by having namespace and enum use ::
instead of .
, so if we have Foo::bar
we know that Foo
is an enum type or namespace and not a global or a property
Alternatively could also enforce lower case for properties and uppercase for type so that we will not have conflict.
There is also the topic looking up types. Should builtin elements and builtin enum always be in scope, or should they be imported too? Why do we need to import our widget (which, from the user point of view, are also builtin) but not the builtin elements and struct.
The new syntax has the new lookup rules