Skip to content

Latest commit

 

History

History
293 lines (215 loc) · 5.65 KB

code-style.md

File metadata and controls

293 lines (215 loc) · 5.65 KB

Code style

This document describes a code style as applied by the mofmt.

Maximum line length

There is no line length limit. There are plenty of limits already.

Horizontal spacing

Spaces

mofmt uses a single space as a horizontal separator between tokens.

Spaces are not inserted before:

  • semicolons (;), except when preceded by within
  • commas (,)
  • parentheses and brackets (()[]{})
  • dots (.) in type specifiers and names

Spaces are not inserted after:

  • dots (.) in type specifiers and names
  • opening brackets (([{)
Example
parameter .Foo.Bar[10] Baz(start = 0, max = 100);

Operators

Unary

Two kinds of Modelica unary operators are treated differently:

  • not operator is always followed by a space
  • +, -, .+, .- are not followed by a space
Example
-4
.-A
not is_off

Binary

All binary operators are surrounded with spaces.

Example
(-2) * (3 - 1.76)
a <= b or x
1 : 10

Assignments and equalities

:= and = tokens are surrounded with spaces.

Example
foo = bar * 2
Real foo(min = 0, max = 2) = 1 / 2
foo := bar(x)
foo := if x < 2 then bar else baz

Arrays, modifications, function calls, expression lists

Every comma (,) and semicolon (;) is followed by a space. This includes discarded slots in output-expression-list.

Example
{1.0, 2.0, 3.0}
(foo, , bar) := baz(x, y) 
[x, y; a, b]

Vertical spacing

Indentation

Indentation is two spaces per level.

Automatic wrapping

Line is automatically wrapped before every:

  • class definition
  • element
  • equation
  • statement
  • description string
  • annotation
  • constraining clause
  • enumeration item

In case of:

  • class definition
  • element
  • equation
  • statement

wrap can be doubled so there is a single blank line instead.

Automatic blank lines

Section keywords:

  • public
  • protected
  • equation
  • algorithm
  • external

are always preceded and followed by a blank line. Those keywords are placed without indentation.

Blank lines are also inserted:

  • at the beginning and end of the composition rule
  • before the "lass-wide annotation in the composition rule
Example
within SomePackage;
final model Foo
                                    // AUTO BLANK
  Real x;
  Real y;
                                    // AUTO BLANK
protected
                                    // AUTO BLANK
  Real z;
                                    // AUTO BLANK
equation
                                    // AUTO BLANK
  x + y = z;
  x * 2 = y;
                                    // OPTIONAL BLANK
  z = 3 ^ 2;
                                    // AUTO BLANK
  annotation ();
                                    // AUTO BLANK
end foo;
                                    // OPTIONAL BLANK
partial record Bar
                                    // AUTO BLANK
  parameter Boolean is_off = false;
                                    // AUTO BLANK
end Bar;

Descriptions, annotations and constraining clauses

Indentation is increased only one per element.

Example
replaceable package Medium = Modelica.Media.R134a.R134a_ph
  constrainedby Modelica.Media.Interfaces.PartialMedium
  "Fluid medium"
  annotation(Dialog(tab = "General", group = "Medium"));

But not:

replaceable package Medium = Modelica.Media.R134a.R134a_ph
  constrainedby Modelica.Media.Interfaces.PartialMedium
    "Fluid medium"
      annotation(Dialog(tab = "General", group = "Medium"));

Enumeration items

Indentation is increased inside enumeration() and at every description.

type BoundaryType = enumeration(
  Pressure
    "Pressure boundary",
  Flow
    "Flow boundary")
  "Enumeration of possible boundary types";

Loops and ifs

Indentation is increased once per block.

Example
if foo == bar then
  baz := bark;
  bam := bem;
else
  if some_condition then
    baz := 0;
    bam := 1;
  else
    baz := bam;
  end if;
end if;

Manual wrapping

Function calls, arrays, matrices, modifications, lists

The main rule here is: be consistent. The following approach is applied:

  1. If a line was originally wrapped at any argument in the specific construct, then wrap at every argument in this construct.
  2. If a line was originally wrapped inside a nested construct, then wrap at every argument in every outer construct.

Indentation is increased accordingly to help visually identify the scope.

Example
// No wrap is fine
h = enthalpy_pT(p, T)

// Outer array is wrapped, but inner ones are kept intact
parameter Real A[2, 3] = {
  {1.0, 2.0, 3.0},
  {5.0, 6.0, 7.0}}

// In nested function call, if inner call is wrapped, outer call is
// wrapped as well
cp_a = specificHeat_pT(
  p = p_a,
  T = temperature_ph(
    p = p_a,
    h = h_a))

// But it is fine to wrap only outer call, keeping inner one intact
cp_b = specificHeat_pT(
  p = p_b,
  T = temperature_ph(p = p_b, h = h_b));

// Wrapped comprehensions are little bit special
{
  a[i] * b[i]
  for i in 1 : n}

// Import lists
import Modelica.Constants.{
  pi,
  inf};

Expressions

Expressions like arithmetic, logical etc. are handled in a different way, because mofmt doesn't apply autowrapping when it detects a wrap in the original file. Original wraps are preserved, and indentation is adjusted. Indentation is increased only once per expression.

Other difference is that instead of commas line may be wrapped before binary operators.

Example
// No wrap
foo := 2 * (bar - baz) / 5

// Single wrap
foo := 2
  * (bar - baz) / 5

// Two wraps
foo := 2
  * (bar - baz)
  / 5