modelica / ModelicaSpecification

Specification of the Modelica Language
https://specification.modelica.org
Creative Commons Attribution Share Alike 4.0 International
102 stars 41 forks source link

Can functions be called with arguments that are subtypes of the declared input arguments? #3103

Open casella opened 2 years ago

casella commented 2 years ago

Consider the following MWE:

package TestFunctionInputType
  record BaseR
    constant Integer n = 3;
    Real x[n];
  end BaseR;

  record DerivedR
    extends BaseR(n = 5);
  end DerivedR;

  function f
    input BaseR r;
    output Real y;
  algorithm
    y := sum(r);
  end f;

  model M
    DerivedR r(x={1, 2, 3, 4, 5});
    Real y;
  equation
    y = f(r);
  end M;
end TestFunctionInputType;

Is the function call in model M legal? The Specification, Section 12.4.1 states:

The type of each argument must agree with the type of the corresponding parameter

Strictly speaking, this is not the case, since r contains a record x of size 5, while the input argument of function f contains a record with size 3, so the types do not agree. For this reason, as reported by @perost, OMC rejects this MWE. Dymola instead accepts it.

My understanding is that, despite Modelica claiming to be an object-oriented languages, there is no such thing as polymorphism in Modelica functions, unlike OO languages like C++ or Java. The introduction of Chapter 6, explicitly mentions the only cases where polymorphism is allowed: replaceable classes and inner/outer elements. This has nothing to do with function inputs, so I guess 12.4.1 should be interpreted strictly and model M should be rejected.

What is the interpretation of the language group?

eshmoylova commented 2 years ago

I tried the model in MapleSim. It fails. But not because of the type of the input mismatch. There is a type mismatch in the statement:

y := sum(r);

where you assign the result of record summation into a Real. I believe it should not be possible to perform summation on a record either unless it is an operator record. I checked what I get in OpenModelica. There I also get that the problem is in assigning record into a Real.

[Type mismatch in assignment in y := sum(r) of Real := TestFunctionInputType.BaseR]

I might have an older version: Connected to OpenModelica v1.16.2 (64-bit) Connected to OMSimulator v2.1.0-dev-230-g10c82c8-mingw

Not saying that the specification is clear. I believe the issue you brought up is valid and needs to be discussed. But just wanted to make sure you were seeing the right error for the right reason.

perost commented 2 years ago

@eshmoylova: Newer versions of OpenModelica rejects it because r isn't an array, and sum requires the argument to be an array. But my original MWE was just:

record BaseR
  constant Integer n = 3;
  Real x[n];
end BaseR;

record DerivedR
  extends BaseR(n = 5);
end DerivedR;

function f
  input BaseR r;
end f;

model M
  DerivedR r;
algorithm
  f(r);
end M;

It seems @casella added some bits to it in order to attempt to make it a balanced model (which I usually don't bother with for this kind of issue), but got it a bit wrong. But the body of the function doesn't matter, the question is about whether the argument is legal or not.

casella commented 2 years ago

Sorry, of course I meant this

package TestFunctionInputType
  record BaseR
    constant Integer n = 3;
    Real x[n];
  end BaseR;

  record DerivedR
    extends BaseR(n = 5);
  end DerivedR;

  function f
    input BaseR r;
    output Real y;
  algorithm
    y := sum(r.x);
  end f;

  model M
    DerivedR r(x={1, 2, 3, 4, 5});
    Real y;
  equation
    y = f(r);
  end M;
end TestFunctionInputType;

but in any case, as @perost pointed out, the question is whether the argument of the function call is legal or not, before even considering running the function.

casella commented 2 years ago

@HansOlsson, @henrikt-ma, @perost, what do you think?

perost commented 2 years ago

@HansOlsson, @henrikt-ma, @perost, what do you think?

The original issue in ClaRa was fixed, so there is no longer any use case for this. As such I can't see any reason why it should be allowed.

casella commented 2 years ago

I agree with @perost, but I'd like to get some feedback from other tool vendors if there is agreement on how to interpret the specification in this case.

henrikt-ma commented 2 years ago

My understanding of the Modelica type system is limited, but I wouldn't have expected this to be allowed. On the other hand, it is the kind of matter where I wouldn't have been totally surprised if it turned out that tools are supposed to handle it by instantiating the function differently depending on the types of arguments passed to it.

casella commented 2 years ago

As I understand it, despite the claim the Modelica is an object-oriented language, it doesn't have polymorphism in function calls. The only place where polymorphism is allowed is redeclares. And maybe a little bit of it in operator records.

eshmoylova commented 2 years ago

I finally had a chance to look at it in detail. I am not sure DerivedR is not a type of BaseR. The dimensions of arrays must be the same, but how would you write that down? When generating code for function f with input r as:

  function f
    input BaseR r;
    ...

I would generate the equivalent of the following assertion:

assert(size(r.x,1) == r.n, "dimension mismatch");

And if M.r is passed to f it would still satisfy that assertion. So to me the question is: to which extent the dimensions must be evaluated when functions are generated?