1 edited


  • doc/proposals/vtable.md

    r62315a0 r18d4dbd  
    11Proposal For Use of Virtual Tables
     4This is an adaptation of the earlier virtual proposal, updating it with new
     5ideas, re-framing it and laying out more design decisions. It should
     6eventually replace the earlier proposal, but not all features and syntax have
     7been converted to the new design.
    49The basic concept of a virtual table (vtable) is the same here as in most
    8893        }
    8994    }
    91 With a more complete widget trait you could, for example, construct a UI tool
    92 kit that can declare containers that hold widgets without knowing about the
    93 widget types. Making it reasonable to extend the tool kit.
    9596The trait types can also be used in the types of assertions on traits as well.
    243244We would also like to implement hierarchical relations between types.
    245     ast_node
    246     |-expression_node
    247     | |-operator_expression
    248     |
    249     |-statement_node
    250     | |-goto_statement
    251     |
    252     |-declaration_node
    253       |-using_declaration
    254       |-variable_declaration
     246    AstNode
     247    |-ParseNode
     248    | |-Declaration
     249    | | |-DeclarationWithType
     250    | | |-StructureDeclaration
     251    | |-Statement
     252    | | |-CompoundStatement
     253    | |-Expression
     254    |-Type
    256256Virtual tables by themselves are not quite enough to implement this system.
    315315    }
    317 This system does not support multiple inheritance. The system could be
    318 extended to support it or a limited form (ex. you may have multiple parents
    319 but they may not have a common ancestor). However this proposal focuses just
    320 on using hierachy as organization. Other uses for reusable/genaric code or
    321 shared interfaces is left for other features of the language.
    323317### Extension: Structural Inheritance
    324318An extension would be allow structures to be used as internal nodes on the
    360354solution but only works if we have exactly 1 vtable for each type. The second
    361355is to put a pointer to the type id in each vtable. This has more overhead but
    362 allows multiple vtables per type.
     356allows multiple vtables.
    364358    struct <trait>_vtable {
    373367        // Trait dependent list of vtable members.
    374368    };
    376 One important restriction is that only one instance of each typeid in memory.
    377 There is a ".gnu.linkonce" feature in the linker that might solve the issue.
    379370### Virtual Casts
    432423    io_error * error = (virtual)exc;
    434 #### Sample Implementation
    435 This cast implementation assumes a type id layout similar to the one given
    436 above. Also this code is definitely in the underlying C. Functions that give
    437 this functionality could exist in the standard library but these are meant to
    438 be produced by code translation of the virtual cast.
    440     bool is_in_subtree(typeid const * root, typeid const * id) {
    441         if (root == id) {
    442             return true
    443         } else if (NULL == id->parent) {
    444             return false;
    445         } else {
    446             return is_in_subtree(root, id->parent);
    447         }
    448     }
    450     void * virtual_cast(typeid const * target, void * value) {
    451         return is_in_subtree(target, *(typeid const **)value) ? value : NULL;
    452     }
    454 The virtual cast function might have to be wrapped with some casts to make it
    455 compile without warning.
    457 For the implicate target type we may be able to lean on the type resolution
    458 system that already exists. If the casting to ancestor type is built into
    459 the resolution then the impicate target could be decided by picking an
    460 overload, generated for each hierarchial type (here io_error and its root
    461 type exception).
    463     io_error * virtual_cast(exception * value) {
    464         return virtual_cast(io_error_typeid, value);
    465     }
    467425### Extension: Inline vtables
    468426Since the structures here are usually made to be turned into trait objects
    478436to allow access to all three options.
    480 The pointer to virtual table field on structures might implicately added (the
    481 types have to declare they are a child here) or created with a declaration,
    482 possibly like the one used to create the assertion.
    484438### Virtual Tables as Types
    485439Here we consider encoding plus the implementation of functions on it to be a
    488442and implementation.
    490 ### Question: Wrapping Structures
    491 One issue is what to do with concrete types at the base of the type tree.
    492 When we are working with the concrete type generally it would like them to be
    493 regular structures with direct calls. On the other hand for interactions with
    494 other types in the hierarchy it is more convenent for the type already to be
    495 cast.
    497 Which of these two should we use? Should we support both and if so how do we
    498 choose which one is being used at any given time.
    500 On a related note I have been using pointers two trait types here, as that
    501 is how many existing languages handle it. However the generic objects might
    502 be only one or two pointers wide passing the objects as a whole would not
    503 be very expensive and all operations on the generic objects probably have
    504 to be defined anyways.
    506444Resolution Scope
    596534Stack allocated functions interact badly with this because they are not
    597535static. There are several ways to try to resolve this, however without a
    598 general solution most can keep vtables from making the existing thunk problem
    599 worse, they don't do anything to solve it.
     536general solution most can only buy time.
    601538Filling in some fields of a static vtable could cause issues on a recursive
    612549shortest lifetime of a function assigned to it. However this still limits the
    613550lifetime "implicitly" and returns to the original problem with thunks.
    615 Odds And Ends
    616 -------------
    618 In addition to the main design there are a few extras that should be
    619 considered. They are not part of the core design but make the new uses fully
    620 featured.
    622 ### Extension: Parent-Child Assertion
    623 For hierarchy types in regular traits, generic functions or generic structures
    624 we may want to be able to check parent-child relationships between two types
    625 given. For this we might have to add another primitive assertion. It would
    626 have the following form if declared in code:
    628     trait is_parent_child(dtype Parent, dtype Child) { <built-in magic> }
    630 This assertion is satified if Parent is an ancestor of Child in a hierarchy.
    631 In other words Child can be statically cast to Parent. The cast from Parent
    632 to child would be dynamically checked as usual.
    634 However in this form there are two concerns. The first that Parent will
    635 usually be consistent for a given use, it will not be a variable. Second is
    636 that we may also need the assertion functions. To do any casting/conversions
    637 anyways.
    638 TODO: Talk about when we wrap a concrete type and how that leads to "may".
    640 To this end it may be better that the parent trait combines the usual
    641 assertions plus this new primitive assertion. There may or may not be use
    642 cases for accessing just one half and providing easy access to them may be
    643 required depending on how that turns out.
    645     trait Parent(dtype T | interface(T)) virtual(<grand-parent?>) { }
    647 ### Extension: sizeof Compatablity
    648 Trait types are always sized, it may even be a fixed size like how pointers
    649 have the same size regardless of what they point at. However their contents
    650 may or may not be of a known size (if the `sized(...)` assertion is used).
    652 Currently there is no way to access this information. If it is needed a
    653 special syntax would have to be added. Here a special case of `sizeof` is
    654 used.
    656     struct line aLine;
    657     trait drawable widget = aLine;
    659     size_t x = sizeof(widget);
    660     size_t y = sizeof(trait drawable);
    662 As usual `y`, size of the type, is the size of the local storage used to put
    663 the value into. The other case `x` checks the saved stored value in the
    664 virtual table and returns that.
Note: See TracChangeset for help on using the changeset viewer.