Search code examples
dml-lang

DML 1.4 template inheritance


We are converting our register_alias template from DML 1.2 to DML 1.4. After a few iterations, we were able to get this to work with the help of some helpful compiler warnings. Here is what we got:

template register_alias {
    param target default undefined;
    param allocate = false;
    is (_set, _get, register);

    method read_register(uint64 enabled_bytes, void* aux) -> (uint64) {
        local uint64 val;
        val = target.read_register(enabled_bytes, aux);
        log info: "register_alias read_register()";
        return val;
    }

    method write_register(uint64 value, uint64 enabled_bytes, void *aux) {
        log info: "register_alias write_register()";
        target.write_register(value, enabled_bytes, aux);
    }

    method get() -> (uint64) {
        local uint64 val;
        log info: "register_alias get()";
        val = target.get();
        return val;
    }

    method set(uint64 val) {
        log info: "register_alias set()";
        target.set(val);
    }

}

This works, but we wonder why we need to have the following in the template?

is (_set, _get, register);

We thought that when applying a template, it inherits the attributes of the objects on which the template is applied to i.e. in this case the register itself which I believe also uses the _set, _get and register templates.


Solution

  • I assume you got _set/_get from the hints given by EAMBINH. They are not documented (as the leading underscores also hints), and thus unsupported/subject to change. If you explore dml-builtins, you'll see that the register template instantiates set and get, which in turn instantiate _set and _get, respectively. So, is register; is in fact sufficient, and a safer choice.

    To answer your question, these templates are needed to resolve overrides: E.g., a bare register object comes with one implementation of read_register, through the builtin register template, and if you instantiate register_alias in the register there will be two conflicting implementations of the method. The is register declaration tells DML that the declaration from register_alias takes precedence. The crucial thing here is that without is register, the register_alias template itself has no relation to register objects, it can just as well be applied to e.g. group objects. This means that the method declarations inside the register_alias template do not have a relation to the declarations in the register template, which results in an ambiguity.

    For formal details, please see the Default Methods section of the reference manual.

    The reason why this isn't needed in DML 1.2, is that non-default implementations were given precedence over default implementations in some situations. This usually worked OK when there was only one level of overrides, but could give confusing results with multiple levels of overrides. In DML 1.4, the only semantics of the default annotation on a method is that overrides are permitted; this is more regular compared to DML 1.2, and also consistent with how other OO languages tend to work.