summaryrefslogtreecommitdiff
path: root/pages/contrib/docs/eo.md.txt
blob: fe1a1b97d6ebf4fe637497149ca13e5dc6bd7816 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
---
~~Title: Eolian File Format Specification~~
---

# Eolian File Format Specification #

## Language Quick Reference ##

This is the quick reference, for a full definition see [Format in EBNF](#Eolian_File_Format)

 * General:
   * ``/* comment */`` or ``//`` are comments like in C/C++, they are used to explain the statements surrounding them. It's ignored and will never go to the generated files.
   * ``[[ documentation ]]`` will be transformed into documentation for their associated object (variable, class, method, property, enum, type...). In C, that goes as a doxygen-style comment in the generated header file, so do not confuse it with a regular ``/* comment */``.
   When a comment sits alone on its own line, it refers to the text on the next line. When it sits at the end of a line, it refers to the previous text in that same line.
   * Groups and blocks are defined within ``{`` and ``}``
   * Some modifiers may be used, their meaning and scope are defined per context, such as ``@extern`` may be used with ``type``, ``enum`` and ``struct`` to denote they are already declared elsewhere (like an included header).
   * Optional components are defined with ``[`` and ``]``.
 * Basic Definitions:
   * **Variables**: ``var [@extern]  name : type [= value] ;``
   * **Constant**: ``const name : type = value ;``
   * **Enumeration**: ``enum [@extern] name { field1, field2 [= value2] ... }``
 * Structure Definitions:
   * **Opaque**: ``struct [@extern] name ;``
   * **Opaque with free function**: ``struct @free( free_function ) name ;``
   * **With fields**: ``struct name { field1 : type1 , field2 : type2 ... } ;``
 * Type Definitions:
   * **Simple**: ``type [@extern] name : other ;``
   * **Simple with free function**: ``type @free( free_function ) name : other ;``
   * **List**: ``type name : list<Child_Type>* ;``
   * **Array**: ``type name : array<Child_Type>* ;``
   * **Hash**: ``type name : hash<Key_Type , Value_Type>* ;``
 * Object Definitions:
   * **Common Body** for class, abstract, interface and mixin: 
     - ``legacy_prefix : prefix ;``
     - ``eo_prefix: prefix ;``
     - ``events { event_name_1 [@private | @protected | @beta | @hot] : type1 ; event_name_2 : type2 ; ... }``
     - ``methods { list_of_methods_and_properties }``
        - **Methods**: ``name [@protected | @const | @class | @pure_virtual] { method_body }``
          * ``legacy: name ;``
          * ``return: type [(expression)] [@warn_unused];``
          * ``params { [@in | @out | @inout] name1 : type1 [(expression)] [@nonull | @nullable | @optional] ; name2 : type2 , ... }``
        - **Properties**: ``@property name [@protected | @class | @pure_virtual ] { property_body }``
          * ``get [@pure_virtual] [{ return: type ; legacy: name }]``
          * ``set [@pure_virtual] [{ return: type ; legacy: name }]``
          * ``values { name1 : type1 [(expression)] [@nonull | @nullable | @optional] ; name2 : type2 , ... }``
          * ``keys { name1 : type1 [(expression)] [@nonull | @nullable | @optional] ; name2 : type2 , ... }``
   * **Classes**: ``class name ( Base_Class1 , Base_Class2 ) { class_body }``
     - ``data: private_data_type ``
     - ``implements { class.constructor; class.destructor; [@auto | @empty] interface_name1 ; .local_name2 , ... }``
     - ``constructors { method_name1 ; .local_method_name2 , ... }``
   * **Abstract classes**: ``abstract name ( Base_Class1 , Base_Class2 ) { abstract_body }``
     - ``data: private_data_type ``
     - ``implements { class.constructor; class.destructor; [@auto | @empty] interface_name1 ; .local_name2 , ... }``
     - ``constructors { method_name1 ; .local_method_name2 , ... }``
   * **Mixins**: ``mixin name ( Base_Class1 , Base_Class2 ) { mixin_body }``
     - ``data: private_data_type ``
     - ``implements { class.constructor; class.destructor; [@auto | @empty] interface_name1 ; .local_name2 , ... }``
   * **Interfaces**: ``interface name ( Base_Class1 , Base_Class2 ) { interface_body }``
     - ``implements { class.constructor; class.destructor; }``

## Eolian File Format Example ##

Before jumping to read the commented example file you may refer to the [Language Quick Reference](#Language_Quick_Reference) or check the full [Eolian file format](#Eolian_File_Format).

```c
  /* COMMENTS ARE IMPORTANT, READ THEM. */

  import efl_types; /* Import efl_types.eot or efl_types.eo depends on which one exists. */
  
  type Something: int; // Simple type definition
  // complex types and free funcs
  // own() on typedefs means that the "base" type of the alias
  // is owned but not its inner types.
  // free provides the function to be called in order to free the type.
  // It's useful for humans but essential for automatic binding generations.
  type @free(eina_list_free) List_Objects: list<Some.Class>*;
  type @free(my_hash_free) My_Hash: hash<key_type, val_type>*;

  // const syntax: const pointer to const char, think of it like of
  // a "modifier function"
  type Foo: const(const(char)*);

  // immediate free for pointers
  type Bar: free(char *, my_str_free);

  // external structs - defined in the system and not to be generated in C
  struct @extern foo {
      x: int;
      y: float;
  }

  /* external type definitions - Evas.Coord is defined in eina, so no need to
   * generate in C, but generators need to know about it */
  type @extern Evas.Coord: int;

  class Elm.Button (Elm.Layout, Evas.Interface.Clickable) {
      legacy_prefix: elm_button; // To override the default legacy prefix
      eo_prefix: elm_obj_button; // To override the default Eo prefix
      /* To indicate the type for this class. If "null", the data is considered
       * as not present in the class.
       */
      data: Elm_Button_Data;
      methods {
          /* @part means that this method/property supports eo_part */
          @property some_text @part {
              /* When either of set/get is missing, that one is not generated.
               * When both are missing, both are generated. This is a short-cut
               * for prototyping quickly without the docs and extra declarations.
               */

              [[Doc for the property in general. Both set and get.]]
              set {
                  [[Docs - extra for set (optional)]]
              }
              get @pure_virtual { // Only the getter is virtual pure (no implementation)
                  [[Docs -extra for get (optional)]]
                  values { // you can optionally specify keys and values in get/set too
                      text: const(char)*;
                  }
              }
              /* Extra params passed to the setter and getter. Modifiers @in/@out/@inout
               * are *not* supported.
               */
              keys {
                  blah: const(char)*; [[Extra params for both]]
              }
              /* Which values make the property. Modifiers @in/@out/@inout are *not*
               * supported.
               */
              values {
                  text: char*; [[docs]]
              }
          }
          /* This function is a function that should be called when
           * constructing an object, so bindings should put it in the
           * generated constructor - it's marked as constructing below
             in a separate section (constructors) */
          some_constructing_function {
              params {
                  something_important: int;
              }
          }
          foo @class @pure_virtual { /* class method, virtual pure meaning it has no implementation */
              .....
          }
          /* Needed if this is a "const" method, that is, a getter and
           * obj should be const.
           */
          corner_coords_get @const {
              [[Docs.]]
              params {
                  corner: int; [[@in implied.]]
                  @in corner2: int;
                  @in base: char* @nullable; [[NULL is a valid value meaning "default".]]
                  @inout number_of_tries: int; [[Same property in both,
                                                  implies in/out, only one
                                                  documentation needed. Rarely
                                                  used anyway.]]
                  @out cx: Evas.Coord;
                  @out cy: Evas.Coord @optional; [[you can pass NULL if you would like to ignore this value]]
              }
              /* Lack of return implies return void.
               * The (false) implies EINA_FALSE is the default return value in case an error
               * occurs e.g eo_do failing...
               */
              return: bool (false) @warn_unused;
              /* override the legacy function name. If "null", no
               * legacy is created for this function.
               */
              legacy: elm_button_specific_corner_coords_get;
          }
          objects_list_get @protected {
              return: own(list<own(Some.Class)>*);
              /* own indicates that the ownership of the list is given to the
               * caller. We will have the same for @in params to give the
               * ownership to the callee. It means that the owner of the data
               * is responsible for freeing it when no more used.
               * In this example, we indicate that the returned data is a list
               * of Eo objects. Standard types have to be defined and
               * documented inside Eolian documentation, as it is the common
               * library used by all the generators.
               */
          }
      }
      /* Illegal for interface (except ctor/dtor), valid for the rest. */
      implements {
          class.constructor; /* Class constructor. */
          Eo.Base.constructor; /* Default constructor. */

          Elm.Widget.activate;
          Evas.Smart.add;

          .corner_coords_get; /* Name starting with . implies local class. */

          @empty Bla.foo.get; /* Provides an empty implementation.
                               * Either to block calls to the super functions,
                               * or to have a base implementation people can "super" to.
                               */
          @auto Bla.foobar.get; /* Only works on properties (set and get),
                                 * will automatically implement the foo_get function as:
                                 * "return pd->foo;".
                                 */
          /* If there's no modifier (@empty or @auto), it assumed that methods/properties
           * declared in this eo file are implemented, e.g some_part_text_set.
           */
      }
      /* marking as constructing */
      constructors {
          .some_constructing_function;
      }
      events {
          some_private_event @private: int;
          some_new_event: event_info_type;
          /* clicked and many others are there because of inheritance,
           * no need to list them. But there is a need to define the value
           * of the parameter passed when you get that event. Currently
           * lacking here!
           */
          some_unfreezable_event @hot;
      }
  }

  /* Little example on how the namespaces work */
  class Evas.Text (Efl.Interface.Text) {
      methods {
          foo {
              params {
                  x: Elm.Button*; /* translates to: Eo *x */
              }
          }
      }
      implements {
          Efl.Interface.Text.ellipsis.set;
      }
  }

  /* Struct definition */
  struct Some_Plain_Struct {
      some_field: int; [[Docs; parsing goes as <name>: <type>]]
      complex_field: list<int>*;
  }

  /* Opaque structures */
  struct Opaque;

  /* Constants - type is guessed from the value - no support for explicit */
  const some_constant: int = 5;
  const approximate_pi: float = 3.14;

  /* Globals */
  var some_global_var: int;
  var some_global_const_var: const(int);

  /* Global with default value */
  var other_global: int = 10;

  /* Enumerations - only named and global or in typedef */
  enum Foo {
      first_item, [[docs; also, for C usage, field names get uppercased and
                      prefixed with FOO in this case]]
      second_item
  }

  /* Enums allow basic expressions in them; they're purely numerical,
   * evaluated at generation time, and can contain constants (but not variables)
   */
  enum Bar {
      [[enum docs]]
      legacy: baz; /* allows to override the prefix field names use for legacy
                    * C usage - default is guessed by uppercasing enum name
                    */
      first_item  = 1 << 4, [[doc comment]]
      second_item = some_constant * 10,
      tau         = approximate_pi * 2 /* error: integer base only */
  }
```

## Type Context Matrix ##

|                 | Value  | Named struct | Enum   | Pointer | Void   |
| --------------- | ------ | ------------ | ------ | ------- | ------ |
| typedef         |   YES  |     **NO**   | **NO** |   YES   | **NO** |
| return          |   YES  |     **NO**   | **NO** |   YES   | **NO** |
| getter return   |   YES  |     **NO**   | **NO** |   YES   | YES    |
| in param        |   YES  |     **NO**   | **NO** |   YES   | **NO** |
| out/inout param |   YES  |     **NO**   | **NO** |   YES   | YES    |
| event           |   YES  |     **NO**   | **NO** |   YES   | **NO** |
| struct field    |   YES  |     **NO**   | **NO** |   YES   | **NO** |
| function param  |   YES  |     **NO**   | **NO** |   YES   | **NO** |
| subtype         |   YES  |     **NO**   | **NO** |   YES   | **NO** |
| pointer base    |   YES  |     **NO**   | **NO** |   YES   | YES    |
| const modifier  |   YES  |     **NO**   | **NO** |   YES   | YES*   |
| own modifier    | **NO** |     **NO**   | **NO** |   YES   | **NO** |
| free modifier   | **NO** |     **NO**   | **NO** |   YES   | **NO** |

\* Keep in mind that whether const void is allowed or not depends on the outer type. When the const void is a base for a pointer it's allowed, otherwise it is not.

## Builtin Types ##

| Type    | C type             | Comment                          |
| ------- | ------------------ | -------------------------------- |
| byte    | signed char        | Numerical byte                   |
| ubyte   | unsigned char      | Numerical unsigned byte          |
| char    | char               | A character - signed or unsigned |
| short   | signed short       |                                  |
| ushort  | unsigned short     |                                  |
| int     | signed int         |                                  |
| uint    | unsigned int       |                                  |
| long    | signed long        |                                  |
| ulong   | unsigned long      |                                  |
| llong   | signed long long   |                                  |
| ullong  | unsigned long long |                                  |
| int8    | int8_t             | stdint.h                         |
| uint8   | uint8_t            | stdint.h                         |
| int16   | int16_t            | stdint.h                         |
| uint16  | uint16_t           | stdint.h                         |
| int32   | int32_t            | stdint.h                         |
| uint32  | uint32_t           | stdint.h                         |
| int64   | int64_t            | stdint.h                         |
| uint64  | uint64_t           | stdint.h                         |
| int128  | int128_t           | stdint.h                         |
| uint128 | uint128_t          | stdint.h                         |
| size    | size_t             |                                  |
| ssize   | ssize_t            |                                  |
| intptr  | intptr_t           | stdint.h                         |
| uintptr | uintptr_t          | stdint.h                         |
| ptrdiff | ptrdiff_t          |                                  |
| time    | time_t             | time.h                           |
| float   | float              |                                  |
| double  | double             |                                  |
| bool    | Eina_Bool          | Eina type, builtin values true and false mapping to EINA_TRUE and EINA_FALSE |
| void    | void               | Not applicable in some contexts  |
| void_ptr | void * | |
| string | const char * | |
| stringshare| Eina_Stringshare * | |
| generic_value | Eina_Value * | |

## Eolian File Format ##

The description here uses the [extended BNF notation](https://www.ics.uci.edu/~pattis/ICS-33/lectures/ebnf.pdf) to describe the Eolian syntax.

Before jumping on the actual Eolian EBNF, a reminder on the EBNF syntax itself:

 * Comments: ``(* text *)``
 * Definition: ``token ::= sequence``
 * Sequence may be another token or a literal within quotes (``'text'``), order matters.
 * Choices are separated with a stroke (pipe char): ``choice1 | choice2``
 * Options are enclosed within braces: ``[ optional_token ]``
 * Repetitions (zero or more times) are enclosed within curly braces: ``{ repeated_token }``

Thus in the following EBNF you'll see:

| EBNF | Meaning |
|------|---------|
| `` type_complex ::= 'accessor' ``<br>`` | 'array'``<br>`` | 'iterator'``<br>`` | 'hash'``<br>`` | 'list'`` |When ``type_complex`` token is used, one of ``accessor``, ``array``, ``iterator``, ``hash`` or ``list`` strings must be present |
| ``value ::= a-zA-Z0-9_*`` | The token ``value`` must be composed of lower or upper case letters (``a`` to ``z`` and ``A-Z``), as well as numbers (``0`` to ``9``) or the underscore bar (``_``), repeated 0 or more times (``*``) |
| ``name_ns ::= value { '.' value }`` | When ``name_ns`` token is used it may be a token ``value`` with a repetition of the string ``.`` followed by other token ``value``, such as ``My.Token.With.Repetition`` |

```ocaml
  (* Base definitions *)
  
  chunk   ::= [ '#version' integer ] { unit }
  integer ::= 0-9*
  value   ::= a-zA-Z0-9_*
  name_ns ::= value { '.' value }
  name    ::= value
  comment ::= '[[' any character ']]'
  
  c_name_qual ::= '@c_name' '(' name ')'
  
  (*
   * An unit is a basic unit of parsing in Eolian, aka all toplevel elements
   * (that includes different types of classes, named structs and typedefs)
   *)
  
  unit ::= 'abstract'  class_hdr '{' [ comment ] { class_body       } '}'
         | 'class'     class_hdr '{' [ comment ] { class_body       } '}'
         | 'mixin'     mixin_hdr '{' [ comment ] { class_body_mixin } '}'
         | 'interface' iface_hdr '{' [ comment ] { class_body_iface } '}'
         | ('import' | 'parse') name ';'
         | 'type' { type_struct_attrs } name_ns ':' (type | struct | enum) ';'
             [ comment ]
         | 'function' { '@extern' | '@beta' | c_name_qual } name_ns '{'
             [ comment ] { method_body } '}'
         | 'const' { '@extern' | '@beta' | c_name_qual } name_ns ':'
             type '=' expr ';' [ comment ]
         | 'error' { '@extern' | '@beta' | c_name_qual } name_ns '='
            string ';' [ comment ]
         | struct
         | enum
  
  (*
   * Types - they don't mention builtins or where void is allowed (not grammar)
   *)
  
  type_complex_owning ::= 'array' | 'list' | 'future'
  type_complex_view   ::= 'accesssor' | 'iterator' | 'slice' | 'rw_slice'
  
  (* standard type definition - without named structs *)
  type ::= 'const' '(' type     ')'
         | error '(' name_ns { ',' name_ns } ')'
         | type_complex_owning '<' type [ '@move' ] '>'
         | type_complex_view '<' type '>'
         | name_ns
  
  (* attributes for structs and typedefs *)
  type_struct_attrs ::= '@extern' | '@beta' | c_name_qual | '@free' '(' name ')'
  
  (* named struct definition *)
  struct ::= 'struct' { type_struct_attrs } name_ns (';' | '{' [ comment ]
             { struct_field } '}')
  
  (* struct field definition *)
  struct_field ::= name ':' type { '@by_ref' | '@move' } ';' [ comment ]
  
  (* enum definition *)
  enum ::= 'enum' { '@extern' | '@beta' | c_name_qual } name_ns '{'
           [ comment ] enum_field { ',' [ comment ] enum_field } [ comment ] '}'
  
  (* enum field definition *)
  enum_field ::= name [ '=' expr ]
  
  (*
   * Expressions - we don't handle operator precedences here
   *)
  
  expr ::= 'true' | 'false' | 'null' | number | string | character
         | expr binop expr | unop expr | name_ns
  
  number ::= a number literal, described elsewhere
  
  string ::= a string literal, described elsewhere
  
  character ::= a character literal, described elsewhere
  
  binop ::= binary operator, described elsewhere
  
  unop ::= unary operator, described elsewhere
  
  (*
   * Classes - everything related to class grammar
   *)
  
  (* class header - name + optional inherits *)
  
  class_hdr ::= { '@beta' | c_name_qual }
                name_ns [ 'extends' name_ns ]
                [ 'implements' name_ns { ',' name_ns } ]
                [ 'composites' name_ns { ',' name_ns } ]
  
  mixin_hdr ::= { '@beta' | c_name_qual }
                name_ns [ 'requires' name_ns { ',' name_ns } ]
                [ 'extends' name_ns { ',' name_ns } ]
                [ 'composites' name_ns { ',' name_ns } ]
  
  iface_hdr ::= { '@beta' | c_name_qual }
                name_ns [ 'extends' name_ns { ',' name_ns } ]
  
  (* common members shared by different class types *)
  class_body_common ::= 'event_c_prefix' ':' value ';'
                      | 'c_prefix'       ':' value ';'
                      | 'methods'       '{' { method | property } '}'
                      | 'events'        '{' { event             } '}'
                      | 'parts'         '{' { part              } '}'
  
  (* data member - not used for interfaces, used elsewhere *)
  class_body_data ::= 'data' ':' value ';'
  
  (* implements - the full form is allowed in everything but interfaces *)
  class_body_impls ::= 'implements' '{' { impl } '}'
  
  (* constructors - for class/abstract *)
  class_body_ctors ::= 'constructors' '{' { [ '.' ] name_ns [ '@optional' ] ';' } '}'
  
  (* members of regular classes, aka not interfaces or mixins *)
  class_body ::= class_body_common
               | class_body_data
               | class_body_impls
               | class_body_ctors
  
  (* members of interfaces - includes custom impl restrictions *)
  class_body_iface ::= class_body_common
                     | 'implements' '{' { impl_common } '}'
  
  (* members of mixins - like normal but doesn't allow ctors *)
  class_body_mixin ::= class_body_common
                     | class_body_data
                     | class_body_impls
  
  (* implements that are allowed everywhere *)
  impl_common ::= 'class' '.' ('constructor' | 'destructor') ';'
  
  (* implements specific for classes and mixins *)
  
  impl_quals ::= '@auto' | '@empty'
  impl_prop  ::= [ impl_quals ] [ comment ] ';'
  
  impl ::= impl_common | [ impl_quals ] [ '.' ] name_ns
           ( '{' [ 'get' impl_prop ] [ 'set' impl_prop ] '}' | ';' [ comment ] )
  
  (* how an event is defined *)
  event ::= name { ',' name } {
            '@private' | '@protected' | '@beta' | '@hot' | '@restart' }
            [ ':' type ] ';'
  
  (* how a part is defined *)
  part ::= name [ '@beta' ] ':' name_ns ';' [ comment ]
  
  (*
   * Everything related to constructors, methods and properties
   *)
  
  (* method, like constructor but more modifiers *)
  method ::= name { '@protected' | '@const' | '@static' | '@beta' | '@pure_virtual' }
                 '{' [ comment ] { method_body } '}'
  
  (* inside of a method *)
  method_body ::= return | 'params' '{' { param } '}'
  
  (* property, has accessors *)
  property ::= '@property' name { '@protected' | '@static' | '@pure_virtual' | '@beta' } '{' { property_body } '}'
  
  (* property body - get/set accessors, keys, values *)
  property_body ::= 'get' { '@pure_virtual' | '@protected' } '{' [ comment ] { return | 'keys' '{' { param_nodir } '}' | 'values' '{' { param_nodir } '}' } '}'
                  | 'set' { '@pure_virtual' | '@protected' } '{' [ comment ] { return | 'keys' '{' { param_nodir } '}' | 'values' '{' { param_nodir } '}' } '}'
                  | 'keys'   '{' { param_nodir } '}'
                  | 'values' '{' { param_nodir } '}'
  
  (* parameter without direction - implied @in *)
  param_nodir ::= name ':' type [ '(' expr ')' ] [ {  '@by_ref' | '@move' | '@optional' } ]
                  ';' [ comment ]
  
  (* parameter with direction - @in/@out/@inout *)
  param ::= [ '@in' | '@out' | '@inout' ] param_nodir
  
  return_suffix ::=  [ '(' expr ')' ] { '@no_unused' | '@move' | '@by_ref' } ';' [ comment ]
  
  (* return statement - used in methods and accessors - can have a default val *)
  return ::= 'return' ':' type return_suffix
```

## Eo Expressions ##

Eo files support expressions within certain contexts. These expressions can then be evaluated using the Eolian API. There are several types of expressions:

### Simple Expressions ###

These include "true", "false" and "null", besides the ones below. The former two are used in boolean contexts while the latter is used for pointers of any kind.

#### Numerical Expressions ####

Eolian numbers follow C syntax. They, however, don't support octal. They support type suffixes (case insensitive): ``U`` (unsigned int), ``L`` (long), ``UL`` (unsigned long), ``LL`` (long long), ``ULL`` (unsigned long long), ``F`` (float). Without suffix, the literal is either a signed integer or double depending on whether it contains a floating point.

Examples include:
```
5, 3.14, 2.0f, 50ULL, 0xFF, 0xF3UL.
```

#### Strings ####

Strings are enclosed within double quotes. They can contain any character except a newline (except when escaped). They support several escape sequences: ``"\a"``, ``"\b"``, ``"\f"``, ``"\n"``, ``"\r"``, ``"\t"``, ``"\v"`` (same as in C), plus ``"\""`` and ``"\'"`` to escape quotes (single quotes can remain unescaped, but the lexer will accept escaped too) and arbitrary integer and hex escape sequences ``"\ddd"`` and ``"\xXX"``. A backslash character at the end of the line allows the string to span multiple lines (the newline will be included).

Example:

```
"hello world: \xAB \160 \83 \n \
foo"
```
#### Characters ####

A single character. Maps to builtin type **char**. Enclosed within single quotes. Can be either an arbitrary byte (represented within the Eo file, typically as UTF-8) or an escape sequence identical to the ones of strings. Cannot represent Unicode characters - it's just 1 byte. For example: ``' a' ``, ``' \t' ``

### Unary Expressions ###

There are 4 unary operators in Eolian, all with equal precedence level (see table below).

The unary ``+`` operator is a no-op, but it enforces typechecking - it must be used in a context that accepts a signed int and its operand must qualify as a signed int. The unary ``-`` operator acts as a standard unary minus and it typechecks identically to unary plus.

The ``!`` operator is a logical "not" and its operand must qualify either as an arbitrary number or a boolean. Its result is always a boolean.

The ``~`` operator is a bitwise "not". Its operand must qualify as an integer and its result is again an integer (of the same type).

### Binary Operators ###

The binary operators include standard arithmetic (``+``, ``-``, ``*``, ``/``, ``%``) - these act on numbers and yield a number of type identical to one of operands (subject to promotion, see below).

Other operators include comparison operators ``==``, ``!=``, ``>``, ``<``, ``>=``, ``<=``. On the former two, operands can be of any type. On the others, operands must be numbers. The "and" and "or" operators (with syntax ``&&`` and ``||`` take any types as operands. Comparison operators and and/or yield booleans. Keep in mind that if one of the operands for any of these expressions is non-numerical, the other operand must be of the same type.

Finally, there are bitwise binary operators ``&``, ``|``, ``^``, ``<<`` and ``>>`` for bitwise AND, OR, XOR, left and right shift respectively. The operands must qualify as integers and it yields again an integer with the same type as one of operands (again, subject to promotion).

Promotion rules for numbers go as follows:

1) If either of operands is a floating point number, the other operand is promoted to a floating point number of the same type. If both are floating point, the smaller type gets promoted to the larger one.
2) If either operand is unsigned with rank higher or equal to the other operand, the other operand is converted to an unsigned integer of the same type.
3) If either operand is signed with rank higher than the other operand (which can be signed or unsigned), the other operand is converted to a signed integer of the same type.

A few examples: ``float + int == float``, ``unsigned long + long == unsigned long``, ``long + unsigned int == long``.

#### Operator Precedence ####

What follows is a precedence table of operators in Eolian, from higher to lower precedence.

| Precedence                    |
| ----------------------------- |
|  unary operators (+, -, ~, !) |
|  *, /, %                      |
|  +, -                         |
|  <<, >>                       |
|  &                            |
|  ^                            |
|  \|                           |
|  ==, !=, >, <, >=, <=         |
|  &&                           |
|  \|\|                         |

## Eo File Style Guide ##

- Variable names: ``foo_bar``
- Class names: ``Foo.Bar``
- Type names: ``Foo.Bar``
- Enum names: ``Foo.Bar``
- Indentation: 3 spaces per level
- Brace placement: Opening brace on the same line with previous code, closing brace aligned with first non-whitespace character of the line with the opening brace
- Please try to keep line length below 120 columns.
- Put a space before every opening brace as well as before inherits list.

You can find handy syntax highlighting config files for different editors [here](https://git.enlightenment.org/editors).

## Common Eolian Mistakes ##

1. ``legacy_prefix: null;`` - deprecated, do not use.
1. The default naming is the class/struct/enum name all in lower case with periods replaced with _ (e.g. Elm.Widget.Item -> elm_widget_item). No need to set it to that value.
1. Document the properties themselves, not the set/get sections separately. For example look at [Efl.Image.smooth_scale](https://git.enlightenment.org/core/efl.git/tree/src/lib/efl/interfaces/efl_image.eo#n25) for an example:

        @property smooth_scale {
            [[Whether to use high-quality image scaling algorithm for this image.

            When enabled, a higher quality image scaling algorithm is used
            when scaling images to sizes other than the source image's
            original one. This gives better results but is more
            computationally expensive.

            $true by default
            ]]
            set {}
            get {}
            values {
                smooth_scale: bool; [[Whether to use smooth scale or not.]]
            }
        }

## Beta-only features and transitioning old Eo files

### Pointers

Old Eolian had a pointer syntax `ptr(T)`. Example:

```
param: ptr(Some.Struct);
```

This syntax is currently working in beta-tagged APIs for transition purposes,
but should not be used in stable API. What you should use instead is the new
`@by_ref` tag. It applies in multiple contexts:

```
return: T @by_ref;
@in param: T @by_ref;
struct_field: T @by_ref;
```

### Enum legacy field

Old Eolian used to allow the `legacy` keyword to be used in enums to set
the C prefix. This was a misnomer.

```
enum Foo {
    legacy: BAR;
    ...
}
```

There is no replacement for this feature.

### Owning

The old `@owned` tag is now called `@move`.

### Freeing functions

Old Eolian used to allow `free(T, func)` to specify freeing functions on
arbitrary types. It also had default fallbacks for freeing certain builtins.
This is not allowed by modern Eolian. No builtins are offered (the generator
is supposed to know them) and specifying custom freeing functions is only
allowed on structs (with the same old `@free(func)` syntax).

### Disallowed types

There are some types allowed in beta but not allowed in stable.
These include `__undefined_type`, `hash<K, V>`, `void_ptr`.

### Inheritance syntax

Old Eolian specified inheritance all in a single section like this:

```
class Foo(Bar, Baz, ...)
```

New Eolian has sections:

```
class Foo extends Bar implements Baz, ... composites ...
interface Foo extends Bar, Baz, ... composites ...
mixin Foo requires Bar extends Baz, ... composites ...
```

### Composites section

This is now specified in the inheritance part instead of a section in the
class body. Putting an interface in the composites section also automatically
puts it in implements/extends if it isn't already found in the inheritance tree.

### Misc renames

The `any_value_ptr` builtin is now called `any_value_ref`.

### Other notes

Generally, the Eolian parser will guide you through transitioning. You can
more or less assume that if the parser does not error, your Eo file should
be all right; otherwise, error messages should tell you what's wrong.