This finally enables looking up things from the current unit
rather than from a backing storage in the Eolian state. This
also means that the benefits of having a unit system will
finally be visible.
This makes sure variables are stored as well as types within their
respective units. Also, declarations are now refcounted just like
any other Eolian object.
Eolian now properly merges all unit hashes (e.g. unit A has
children B and C, hashes of B and C are merged into A's hashes
in order to be able to look up B and C's contents via A) and
maintains a (potentially cyclic) children graph.
Not everything is yet added into all hashes, but at least the
building blocks are there.
This change finally introduces deferred parsing of inherits to
Eolian, after a long time and many iterations. That means instead
of parsing inherits directly as part of the main file's parse pass,
they're pushed into a queue and parsed later. The validation engine
was modified to properly fill in the remaining info afterwards.
This may introduce breakages but I haven't noticed any. It also
properly unlocks cyclic dependency support in Eolian.
Additionally, this also introduces checks for duplicates in class
inherits (class Foo(Bar, Bar) is no longer possible) and it adds
stricter name checks, so you can no longer have a class Foo.Bar
and refer to it as Foo_Bar in implements. This was actually never
meant to be supported, but the check was previously broken.
@feature
For one, the hash has to be populated once per inheritance tree
and the skipping on already-validated funcs was interfering with
that as the function might have been validated in another
inheritance tree already.
Also, if a class appeared multiple times in an inheritance tree,
as is common with e.g. Efl.Object, it would get added into the
hash the first time and then checked against the second time,
which would result in a strange error message about the
function being redefined in its own class.
So now we prevent both cases from happening.
As it is no longer necessary to pass unit when evaluating exprs,
it is not necessary to pass it here either. Convert all the APIs
to the new style and update all instances in our tree.
This makes sure that duplicate method/part/etc checks are done on
every database update, removing the need for clunky toplevel
checks and improving reliability. It also sacrifices some
performance but it shouldn't be too bad (if a class is already
validated, some checks are avoided to speed things up).
Units now form an actual tree stored in their own hash. This will
later replace all global state of Eolian, by introducing a master
unit that you will pass around.
The check was only done on one of the two functions, resulting in some
unwanted warnings.
EOLIAN_WARN_FUNC_DUPLICATES=1 will show non-beta warnings.
EOLIAN_WARN_FUNC_DUPLICATES=2 will still show all warnings.
This disallows deeply nested pointers, you can only explicitly
ptr() on types that are strictly value types.
For a few cases where it was necessary to override this behavior,
you can use legacy(ptr(x)) as a temporary measure.
This is a "pass by reference to const" equivalent. There is no explicit pointer
and currently it's the same as ptr(const(x)) on the type. However, it is also
usable on properties.
No warnings:
export EOLIAN_WARN_FUNC_DUPLICATES=0
No beta warnings:
export EOLIAN_WARN_FUNC_DUPLICATES=1
All warnings including beta:
export EOLIAN_WARN_FUNC_DUPLICATES=2
EOLIAN_WARN_FUNC_DUPLICATES is not an API and may change in the future
as we improve the tool :)
Most of the time you need to retrieve the class from the string
anyway, so remove this relic of old Eolian and gain some small
performance benefits and extra convenience.
Subtly breaks API but everything should be updated.
These types are of questionable value and the API was not entirely
thought out - remove for now, and if a legitimate use is found
later, they may be readded (with a better API), but typically it
seems best to redesign the bad APIs around safe containers...
This is a new type representing a mutable string (no const).
Regular strings cannot be made mutable with @owned because
they might be hidden behind typedefs.
Even though ownership info belongs to params/returns/etc at syntax
level, we can still store it in the type and turn several API funcs
into one this way.
This is the new ownership system for Eolian, working on params,
returns, struct fields or events directly rather than specifying
ownership at type level. As the new system will evolve it will
gain missing features and necessary checks.
For example, aliases to ownable types are now also ownable,
which wasn't possible in the previous version, where you could
only own actual expanded ownable types.
Summary:
Summary : String buffer returned by eina_strbuf_new() is not freed in some cases
@Fix
Signed-off-by: Uma Devika <u.bodapati@samsung.com>
Reviewers: cedric, tasn, jpeg, raster, singh.amitesh
Subscribers: tanwar.umesh07, yashu21985, cedric, jpeg
Differential Revision: https://phab.enlightenment.org/D5000
First steps toward explicit function pointer support in eolian.
To declare a function pointer type, use the following syntax, similar to
a regular eolian method declaration.
function FunctionName {
params {
...
}
return: Return type
}
Dependencies are now going to be parsed strictly after the main
file, to allow proper dependency cycle behavior in all places. For
now there is correct parsing of deferred deps but they're not
queued yet.
Units are Eolian files (eo/eot). Each unit contains information
about its class, dependencies, variables and types. This allows
for saner checking to be done.
We don't need to keep this in eo files anymore because the APIs
using them are now fully in C. This also allows removal of the
event callback builtin from Eolian.
This allows us to unify retrieval of docs for both regular and
overridden funcs without having two separate APIs. It's currently
missing validation and docgen is still not adjusted properly for
it either, but at least there's this. Enables retrieval of docs
for overridden funcs by default as well.
As there is no need to have separate is_auto, is_empty and
is_pure_virtual for functions and implements (each function has
its own base implement by default) I removed the function ones.
Instead, I added a way to retrieve a function's base implement
so that you can instead do the checks on the implement even when
you only have the function.
I also moved base implement build directly into the parser instead
of the database filler. That allows for significant cleanup. I
also removed distinction of implement pointers in Eolian_Function
for get and set as implements now always contain an entire thing
so the pointer was always the same anyway.
Things should still behave more or less the same, but ordering
of generated functions has changed because ordering of implements
has changed.
Previously one API used just virtual (incorrect) and one used
virtual_pure (which just sounds weird). So unify with a single
name, pure_virtual, similar as in other lanugages.
This does not change eo file syntax yet.
Now all error/unknown/etc values returned from APIs are zero,
previously it was a mix of zeroes and minus ones. Also, some
enums that had no error/invalid value before have one now, which
allows for better distinction between what is an error and what
is an intended result.
Strictness of various Eolian APIs has been enhanced, for example
eolian_class_function_get_by_name now won't return anything if
you request an EOLIAN_PROPERTY and the found func is just an
EOLIAN_PROP_GET, and various APIs won't accept arbitrary inputs
like EOLIAN_UNRESOLVED or EOLIAN_PROPERTY now, instead you will
need to provide EOLIAN_PROP_GET, EOLIAN_PROP_SET or EOLIAN_METHOD
explicitly.
The purpose of this is to reduce potential bugs and fix ambiguous
behavior. Thanks to use of EINA_SAFETY, appropriate errors should
be printed into terminal when an API is used incorrectly.
Now you can't use the same syntax as you would for a method to
implement a property as whole, instead you need to specify the
getter and/or setter explicitly. This is to allow parent classes
to expand their properties without altering behavior of the child
classes.
The system now verifies whether the class of an implement or
constructor exists within the inheritance hierarchy. It also
properly checks duplicates everywhere and prints better error
messages.
Instead of
Other.Class.some_prop.get;
Other.Class.some_prop.set;
you can write
Other.Class.some_prop { get; set; }
The other syntax is deprecated from now on.
New API function eolian_doc_token_ref_get will resolve the kind of
reference in the given token and extract the necessary data you
might need for further use, for example class and function for
methods, or struct and field for struct field. It also supports
event references that will be added into Eolian later.
EFL will be switched to the new resolver (by changing the validator
code) during the next step.
This provides an API to tokenize Eolian docstrings. It does not
yet switch the rest of the infra to it, but it does have tests.
It doesn't verify correctness of references, as that's Eolian's
job. Therefore it's also your job to provide it with strings that
do not contain invalid references. Lua bindings are to come and
a complete switch will be done later.
@feature
Summary:
Currently eolian abbreviates when only the last word of class name and
the first word of method name are same, but this patch abbreviates
generated c name of function to remove all duplicated affix.
For example, "efl_io_closer_fd_closer_fd_set" will be "efl_io_closer_fd_set".
Reviewers: jpeg
Subscribers: cedric
Differential Revision: https://phab.enlightenment.org/D4430
Signed-off-by: Cedric BAIL <cedric@osg.samsung.com>
Both variables and constants can have extern on them (it means the same thing
as in types, they won't get generated in C). This is different from the previous
semantics which only allowed extern on globals, which makes no sense.
Both globals and constants are allowed to have a value (previously only
constants were); constants are required to have a value. Globals having
a value is just a convenience for initialization during source generation.
This is unlike the previous behavior, where the value was optional for both
globals and constants and only allowed when not marked extern, which makes
no sense either.
Obivously, even when globals have a value, they're not allowed to be used
in expressions, as they cannot be evaluated at compile time (they're mutable).
Future is the read only side of a Promise. For now, I am not removing
Eina_Promise until everything is in place, but eventually the promise
type of eolian will be gone.
Adds two new type types, STATIC_ARRAY and TERMINATED_ARRAY. Static arrays are
only allowed as struct members right now - they translate to regular C static
arrays (allowing them elsewhere wouldn't be good, as C isn't very good at
working with the size information). Terminated arrays are basically sequences
of data terminated at the end. The base type of static arrays can be any type
that is not marked ref (explicit ref may get allowed later). The base type of
terminated arrays has the same restriction plus that it has to be either
implicitly reference type (i.e. translating to pointer in C), integer type
or a character. In case of ref types, the terminator is NULL. In case of
integer types, the terminator is a zero. In case of character types, the
terminator is also a zero (null terminator like C strings).
@feature
This implements a new builtin, stringshare, which is replaced with the right
pointer to Eina_Strinshare as necessary. This allows simplifying binding code
(it can call the proper eina APIs, deal with lifetime etc).
It also removes the extern Eina.Stringshare typedef from eina_types.eot, which
was actually incorrect and would generate invalid code in binding generators.
@feature @fix
Somehow, there was code in the tree that apparently isn't tested at all, even
once - if it was, the eo.c logic that performs inheritance checks would be
triggered. I don't know how this could have happened (actually I do, it's
Cedric's fault and he should be publicly shamed for it) but these checks
make sure this will never happen again. But since the code itself appears
to be untested, I don't know if there isn't any other brokenness in it.
But that's beyond the scope of this change, so for now, let's make sure
all our inheritance is at least formally correct.
Also, enable eo_interface.eo generated code in Eo itself so that Eo.Interface
can be used when inheriting.
@fix
Because of this the cyclic check would occasionally have false positives.
By moving deferred eo parsing to the end of the whole parse process, it
can no longer affect the cyclic checker.
@fix
Previously, multi-char tokens (such as strings, docs etc) always put the error
cursor to the end of the token. That was confusing, so now the cursor always
appears at the beginning of the token instead (for multiline tokens, currently
only docs, the line number is also adjusted to point to the first line of the
doc token).
@fix
Inner type can now be retrieved as a base type of the type.
If the type has two inner types or more, there is a new API that allows you to
get the second inner type by calling it on the first one (same would apply to
getting third via second etc.).
This API is simpler to use and doesn't require an iterator.
It's now possible to mark struct fields and function params as "references",
which causes them to become pointers in C (in bindings, they become whatever
is necessary). They're not a part of the type and are much more restricted
than pointers, allowing bindings to be easier. This system will be gradually
utilized and expanded as required.
@feature
Complex types (i.e. list, array, hash, accessor etc.) now do not require
pointers with them anymore (the pointer is implied) and the same goes for
class handles. Eolian now explicitly disallows creating pointers to these
as well. This is the first part of the work to remove pointers from Eolian
completely, with the goal of simplifying the DSL (higher level) and therefore
making it easier for bindings (as well as easier API usage).
@feature
This adds env var EOLIAN_PROPERTY_DOC_WARN which enables extra
warnings for properties that don't have a general doc but have
getter/setter doc. This will eventually become an error and
will be enabled by default. For now it's too verbose.
Previously events used to use class name as a prefix and ignored eo_prefix
when specified. This is no longer the case. Events follow eo_prefix by default
now. In order to get around this for classes where this is undesirable, a new
field event_prefix was added which takes priority over eo_prefix. If neither
is specified, class name is used like previously.
@feature
Add a promise object to allows Eolian interface to include promises
as a way to have asynchronous value return and composibility.
The usage is like this in a .eo file:
class Foo {
methods {
bar {
params {
@inout promise: Promise<int>;
}
}
}
}
Which will create the following API interface:
void foo_bar(Eo* obj, Eina_Promise** promise);
and a Eina_Promise_Owner for the implementation, like this:
void _foo_bar(Eo* obj, Private_Data* pdata, Eina_Promise_Owner* promise);
Signed-off-by: Cedric Bail <cedric@osg.samsung.com>
Reverting this at Felipe's request following my email. There are many
things I strongly object to in this commit. I've touched the surface of
those on the ML (which doesn't work at the moment), though we need to
better discuss it.
The gist:
1. dlsym is a really bad hack that is not even needed.
2. I don't see why eo should even be aware of promises. It's not aware
of list, hash and etc.
3. The eolian changes were done wrong.
This should have been discussed and consulted before done, even if only
because of the amount of hacks it includes and the cross-domain (ecore,
eo and eolian) nature of it.
This reverts commit f9ba80ab33.
Add a promise object that allows Eolian interface to include promises
as a way to have asynchronous value return and composibility.
The usage is like this in a .eo file:
class Foo {
methods {
bar {
params {
promise: Promise<int>;
}
}
}
}
Which will create the following API interface:
void foo_bar(Ecore_Promise** promise);
and the equivalent declaration for implementation.
However, the API function will instantiate the Promise for the
user and the implementer of the class.
This allows generators to silence type errors in validation in order
to reduce duplicate error messages when generating multiple files.
Also adjusted the C generator to only emit type errors when generating
Eo header files.
@feature
We have to use void in a function declaration if we want no function
parameters. Using just empty parenthesis means the function takes an
unspecified number of parameters.
We had it correct for most declarations and this series fixes it for
the rest.
This changes the checks in eolian type API so that you can use the various
type funcs on incompatible types, getting a NULL in return; this allows
simplified generator logic, with error handling done on generator side,
without getting annoying messages from the Eolian lib.
This doesn't quite work yet as path sanitization needs to be done for it to
work correctly. For now this code path is disabled and will be enabled once
all paths are correctly sanitized.