wiki:OpenModelicaStyleGuide

Version 3 (modified by perost, 9 years ago) (diff)

--

Matching

Prefer named arguments
When matching a uniontype, prefer using named arguments to only match what is used. A match using named arguments only needs to be changed if the matched fields change in a uniontype, while a match using positional arguments will always have to be changed if the uniontype changes.
// Prefer this.
case DAE.ARRAY(ty = DAE.T_REAL())  

// Not this.
case DAE.ARRAY(DAE.T_REAL(), _, _) 
Use else for catch-all
Prefer using else when writing a catch-all case:
outValue := match(inExp1, inExp2)
  case (DAE.ICONST(), DAE.ICONST()) then inExp1.integer + inExp2.integer;
  else 0;

  // Avoid this:
  case (_, _) then 0;
  // And this (using 'then' is legal, but unnecessary):
  else then 0;
end match;
Use as only for partial matches
as is usually not necessary when matching a whole input argument, such as this:
_ := match(inExp, inStr)
  local
    DAE.Exp exp;
    String str;

  case (exp as DAE.CALL(path = Absyn.IDENT("sum")), _) then ExpressionDump.printExpStr(exp);
  case (_, str as "someString") then str;
end match;
Prefer using the input parameters directly instead:
outStr := match(inExp, inStr)
  case (DAE.CALL(path = Absyn.IDENT("sum")), _) then ExpressionDump.printExpStr(inExp);
  case (_, "someString") then inStr;
end match;

Error Handling

Use the appropriate method to handle errors
For errors that are of interest to the user, use one of the Error.addXXXMessage functions to print an error/warning message. Always supply the source info when posssible, i.e. prefer using addSourceMessage or addMultiSourceMessage. For cases where it might be of interest to the developers if a function fails, use failtrace and Debug.traceXXX:
if Flags.isSet(Flags.FAILTRACE) then
  Debug.traceln("- Foo.bar failed!");
end if;
For functions that should never fail, use internal errors:
function foo
  input Integer inN;
algorithm
  if inN < 0 then
    Error.addInternalError("Negative number given to foo!", sourceInfo());
  end if;
end foo;
Only print internal errors as a last resort
Internal errors should only be used when something has gone really wrong, and ideally they should never be shown to users. In many cases it's therefore appropriate to check that some other error hasn't already been printed before printing an internal error:
function foo
  ...
protected
  Integer err_count = Error.getNumErrorMessages();
algorithm
  try
    // Something which can fail, and might or might not print an error message if it does fail.
  else
    // Only print an internal error if the above code failed without printing an error message.
    if err_count == Error.getNumErrorMessages() then
      Error.addInternalError(...);
    end if;
  end try;
end foo;