This text has been copied from Chapter 20 of the ASCEND manual.
Parameterized model definitions have the following general form:
MODEL new_type(parameter_list;) «WHERE (where_list;)» «REFINES existing_type«(assignment_list;)»;
The parameter list
A parameter list is a list of statements about the objects that will be passed into the model being defined when an instance of that model is created by IS_A or IS_REFINED_TO. The parameter list is designed to allow a complete statement of the necessary and sufficient conditions to construct the parameterized model. The mechanism implemented is general, however, so it is possible to put less than the necessary information in the parameter list if one seeks to confuse the models re-users. To make parameters easy to understand for users with experience in other computer languages (and to make the implementation much simpler), we define the parameter list as ordered. All the statements in a parameter list, including the last one, must end with a ‘;’. A parameter list looks like:
MODEL test ( x WILL_BE real; n IS_A integer_constant; p[1..n] IS_A integer_constant; q[0..2*n-1] WILL_BE widget; );
Each WILL_BE statement corresponds to a single object that the user must create and pass into the definition of test. We will establish the local name 'x' for the first object passed to the definition of test. 'n' is handled similarly, and it must precede the definition of 'p[1..n]', because it defines the set for the array 'p'. Constant types can also be defined with WILL_BE, though we have used IS_A for the example test.
Each IS_A statement corresponds to a single constant-valued instance or an array of constant-valued instances that we will create as part of the model we are defining. Thus, the user of test must supply an array of constants as the third argument. We will check that the instance supplied is subscripted on the set [1..n] and copy the corresponding values to the array p we create local to the instance of test.
WILL_BE statements can be used to pass complex objects (models) or arrays of objects. Both WILL_BE and IS_A statements can be passed arguments that are more refined than the type listed. If an object that is less refined than the type listed, the instance of parameterized model test will not be compiled. When a parameterized model type is specified with a WILL_BE statement, NO arguments should be given. We are only interested in the formal type of the argument, not how it was constructed.
The WHERE list
We can write structural and equation constraints on the arguments in the WHERE list. Each statement is a WILL_BE_THE_SAME, a WILL_NOT_BE_THE_SAME, an equation written in terms of sets or discrete constants, or a FOR/CHECK statement surrounding a group of such statements. Until all the conditions in the WHERE list are satisfied, an object cannot be constructed using the parameterized definition. If the arguments given to a parameterized type in an IS_A or IS_REFINED_TO statement cannot possibly satisfy the conditions, the IS_A or IS_REFINED_TO statement is abandoned by the compiler. We have not created a WILL_BE_ALIKE statement because formal type compatibility in ASCEND is not really a meaningful guarantee of object compatibility. Object compatibility is much more reliably guaranteed by checking conditions on the structure determining constants of a model instance.
The assignment list
When we declare constant parameters with IS_A, we can in a later refinement of the parameterized model assign their values in the assignment list, thus removing them from the parameter list. If an array of constants is declared with IS_A, then we must assign values to ALL the array elements at the same time if we are going to remove them from the parameter list. If an array element is left out, the type which assigns some of the elements and any subsequent refinements of that type will not be compilable.
Refining parameterized types
Because we wish to make the parameterized model lists represent all the pa- rameters and conditions necessary to use a model of any type, we must repeat the parameters declared in the ancestral type when we make a refinement. If we did not repeat the parameters, the user would be forced to hunt up the (possibly long) chain of types that yield an interesting definition in order to know the list of parameters and conditions that must be satisfied in order to use a model. We repeat all the parameters of the type being refined before we add new ones. The only exception to this is that parameters defined with IS_A and then assigned in the assignment list are not repeated because the user no longer needs to supply these values. A refinement of the model test given in Section 20.1 on the previous page follows.
MODEL expanded_test ( x WILL_BE real; p[1..n] IS_A integer_constant; q[0..2*n-1] WILL_BE better_widget; r[0..q.k] WILL_BE gizmo; ms WILL_BE set OF symbol_constant; ) WHERE ( q.k >= 2; r[0..q.k].giz_part WILL_BE_THE_SAME; ) REFINES test( n :== 4; );
In expanded_test, we see that the type of the array q is more refined than it was in test. We see that constants and sets from inside passed objects, such as q.k, can be used to set the sizes of subseqent array arguments. We see a structural constraint that all the gizmos in the array r must have been constructed with the same giz_part. This condition probably indicates that the gizmo definition takes giz_part as a WILL_BE defined parameter.