Fuzion Logo
fuzion-lang.dev — The Fuzion Language Portal
JavaScript seems to be disabled. Functionality is limited.

Visibility

The visibility of a feature defines where this feature can be accessed.

Scopes

A block consists of indented statements or statements enclosed by braces { }.

A scope is defined by a block. Scopes can be nested. For example the declaration of an inner feature is a statement in a surrounding block or the block in an if-statement is nested in the block that contains the if statement.

Unqualified Visibility

Routines

The unqualified visibility of a routine determines where this routine can be called without a qualifying target t as in t.f. A routine f declared in scope s is visible for an unqualified call in s itself, all nested scopes of s and all inner routines declared in the same scope s or in any nested scope within s:

Fields

Compared to routines, fields are not visible for unqualified calls before their declaration:

Assignment Visibility

Unqualified mutable fields can be the target of an assignment whenever the field is visible for an unqualified call.

Masking

Masking fields, sometimes also called variable shadowing is not allowed in fuzion.

Features declared in inner Blocks

Features declared in inner blocks have visibility restrictions similar to those declared in inner features:

The visibility in loops is a bit more complicated, as shown in this example:

In a loop, within the for-block, index variables that are not iterators can be accessed after their declaration and in the next-part of their declaration (after the comma). Index variables are accessible in the while- and until-blocks. Features declared in the while-block are also accessible in the until-block. The else block can access all index variables before the first iterator index variable (one that uses in in the for-block)

The reason for this complex visibility is that it is guaranteed that a for-block is executed fully before the while block is entered. Additionally, the until-block can only be entered after the while block was fully executed.

On the other hand, the else block may be entered as soon as an iterator index variable reaches the end of the iterated set, so only previously declared index variables are guaranteed to be set.

Qualified Visibility

The qualified visibility determines if a feature f is visible via a qualified access target.f.

Qualified Call Visibility

TBD:

  • features within one source code file should probably be fully visible for qualified accesses within the same file
  • features in another source code file should be made visible, e.g., by a keyword public, to be visible for qualified calls
  • features could be made visible to specific other friend features via visible to friend or, if all subclasses of friend should be included, via visible to * : friend or a similar syntax.

Qualified Assignment Visibility

Qualified assignments are not allowed:

Even qualified assignments to masked outer fields are not allowed:

Module Visibility

A feature declared in another module is visible to other modules only if it is exported from the modules. TBD: Need to decide how to do this, mark it export or similar.

An exported feature f declared in scope s of a module m is visible for an unqualified call in another module m2 if that call happens in a scope s2 that is an inner scope of s and it was not masked.

Unqualified Visibility

Example: In module A:

export a
{
  export x { }
  export b
  {
    export y { }
    public z { }
  }
  public c
  {
    export y { }  // *** illegal, compiler error: cannot export y since outer c is not exported
    public z { }
  }
}

In module B:

a.b.new_feature_in_b
{
  // ... x and y are visible here, c and z are not ...
}

a.c.new_feature_in_b // *** illegal, compiler error: c not exported
{
  // ...
}

Qualified Visibility

Qualified accesses to features of another module are restricted to the features that are exported from that module.

Module Assignment Visibility

No fields declared in another module are visible as the target of an assignment in another module.

Visibility for Inheritance

Some languages treat visibility in heirs of a class differently. Java for example knows protected members and has just introduced sealed classes JEP 360.

For Fuzion, the question is whether it would be useful to make a feature visible as a type without allowing calls to the feature, in particular without allowing calls in an inheritance clause.

TBW: Need to decide if this is important enough and if so, do we need specific language support for this or can this be modelled differently (e.g., by adding a unit type argument to a feature that is made visible only to the permitted heirs)?

Visibility of Types vs. Constructors

In some situations, a type that is defined by a constructor feature should be accessible, but not the constructor itself, e.g.,

Here, we might want to make the type dice.face visible so that one can declare

sum(toss1, toss2 dice.face) => toss1.n + toss2.n

while it should be disallowed to create a new face as in

cheat := dice.face 7

Visibility Modifiers in other languages

Java

private for local visibility, protected for local plus sub-class visibility,   for package visibility, public for unrestricted visibility.

Perl

Perls uses our, my and local to extend the scope of variables in somewhat confusing ways. our and my are, however, short and might be useful as simple markers.

Oberon

Oberon replaces the def-files in Modula-2 by a marker * for everything that is exported.

C

C uses .h files to define what is accessible and static to make a declaration inaccessible by other source files.

Eiffel

Eiffel uses a clients clause in a feature declaration. The clients clause explicitly lists the classes to which a feature is to be visible, while classes ANY and NONE handle the special cases of all classes or private features.

Visibility modifiers in Fuzion

The idea is to have three modifiers priv, module and pub to modify the visibility for calls and when used as type. Since priv is also the default visibility, the priv modifier can be omitted to have private (file local only) visibility.

Visibility
Modifier
Current file Current module Other module
priv or   ✅ Yes❌ No❌ No
module ✅ Yes✅ Yes❌ No
pub ✅ Yes✅ Yes✅ Yes

When a different visibility for a type declared by a constructor is desired, a variant of type:priv, type:module and type:pub can be added to modify the type visibility of constructors.

Visibility
Modifier
For calls As types
Current file Current module Other module Current file Current module Other module
priv, priv type:priv, type:priv or   ✅ Yes❌ No❌ No ✅ Yes❌ No❌ No
priv type:module or type:module ✅ Yes❌ No❌ No ✅ Yes✅ Yes❌ No
priv type:pub or type:pub ✅ Yes❌ No❌ No ✅ Yes✅ Yes✅ Yes
module type:priv ✅ Yes✅ Yes❌ No ✅ Yes❌ No❌ No
module or module type:module ✅ Yes✅ Yes❌ No ✅ Yes✅ Yes❌ No
module type:pub ✅ Yes✅ Yes❌ No ✅ Yes✅ Yes✅ Yes
pub type:priv ✅ Yes✅ Yes✅ Yes ✅ Yes❌ No❌ No
pub type:module ✅ Yes✅ Yes✅ Yes ✅ Yes✅ Yes❌ No
pub or pub type:pub ✅ Yes✅ Yes✅ Yes ✅ Yes✅ Yes✅ Yes

Visibility and feature inheritance

In case complex is exported as a public part of a module, we might not want to expose the fact that it inherits from trigo for implementation purposes, so we can inherit in private:

last changed: 2024-08-13