This code was implemented by User:DanteStroe as part of GSOC2009, and has recently (Feb 2012) been merged into trunk (changeset 3923 through changeset 3931), although further testing is definitely still required. With these additions, the ASCEND now supports certain semantic object associations now. Additional logic is required to process these associations and make them useful in solvers, and and so on.
The existing associations
- ARE_THE_SAME-- merge two existing instances recursively, resulting in one object with two names.
- ARE_ALIKE-- keep the formal types of a list of instances identical, which prevents the user from doing dumb things and enables them to avoid writing most IS_REFINED_TO statements.
- ALIASES-- define a new name by pointing at an existing instance, usually to assemble an array or expose a part buried in a lower-level model.
The proposed associations extensions
- Declarative section: LINK( 'key', comma-separated-list-of-names);
- Methods section: LINK(as-above); UNLINK(as-above);
- Each MODEL instance gets a link table listing the links defined locally (with methods).
- The LINKS defined in the declarative section are fixed and are stored in a link table as part of the TypeDescription.
- The elements defined in the methods may be added and removed by running methods or API (user-interface) calls.
- Redundant entries (identical key and namelist) are ignored with warning.
- Conflicting declarative entries invalidate the typedescription.
- Any instance name (subarrays, atoms, subatomics, relations, models, etc) are allowed in list-of-names.
- Only symbol_constants and symbol literals (single quoted) are allowed as keys.
- A link which is defined in a method and later redefined in a type refinement as a declarative link is allowed. A instantiation warning is generated and the declarative link semantics wins.
- There is no way to make a declarative "down-in" link (link appear in another model scope).
- There is no guarantee that the names in namelist exist, but user many turn on compiler options that generate warnings or compilation errors if the names cannot be resolved to instances.
- There may be a link instance cache table (one for both declarative and method links). Any compiler action will invalidate the contents of this table.
- UNLINK is not declaratively allowed. However, a specially recognized key LINK('ignore', target); will have the same effect for agents using the standard query routines: any link which is the target of an in-scope ignore link will be filtered out before any result is returned.
- Links, thus, have labels like relations. The system will generate them if the user does not.
- link label syntax is like relation label syntax, but links do not appear as model instance children internally except for name exclusion purposes-- they are really typedesc level info.
API functionality (initial) design
symbollist getLinkTypes (instance, bool recursive) /** find all the keys in link table(s), optionally recursive. */ listoflinkobject getLinks(instance, key, bool recursive) /**< get all links matching key, optionally recursive. */ listoflinkobject getLinksReferencing(scopeinstance, key, bool recursive, targetinstance); /**< get all links within scopeinstance that name targetinstance. */ const linktable getLinkTableDeclarative(instance) const linktable getLinkTableProcedural(instance) void addLink(instance, key, namelist) void removeLink(instance, key, namelist) /* or removeLink(link-object) more likely. */ void removeNondeclarativeLinks(instance, key, bool recursive) /**< remove dynamically made links matching key or all if key given is NULL, optionally recursive. */ instancelistlist getLinkInstances(instance, link-object, status) /**< return the instances matching list of names in link. Unresolved names result in a null list entry and a Find status, but best effort is applied rather than fail-fast. Each name in the namelist is expanded to a list of instances, which captures the ascend set semantics usage correctly. */ instancelist getLinkInstancesFlat(instance, link-object, status) /**< as the non-flat version, but any error results in a null list return and all found instances are simply appended to one big gllist. */ bool isDeclarative(link-object) /**< - tell if it's dynamic or not. */ void clearLinkCache(instance); /**< empty instance search optimization. (be very careful using on subtrees!) */ void populateLinkCache(instance) */ /**< fill instance search optimization. */