Skip to content

Commit

Permalink
Merge pull request #1745 from michaellilltokiwa/visibility_rules
Browse files Browse the repository at this point in the history
add first batch of visibilty rules and simple test
  • Loading branch information
fridis committed Aug 4, 2023
2 parents 7f7b1f4 + 6085c4a commit 8b28373
Show file tree
Hide file tree
Showing 27 changed files with 728 additions and 33 deletions.
2 changes: 1 addition & 1 deletion lib/fuzion/sys/fileio.fz
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ module fileio is
# -1 at end of file
# -2 for any other error
#
private read(
module read(
# the file descriptor
fd i64,
# the internal array data representing the container for the bytes to be read from the file
Expand Down
2 changes: 1 addition & 1 deletion lib/fuzion/sys/stdin.fz
Original file line number Diff line number Diff line change
Expand Up @@ -27,5 +27,5 @@
# NYI name in does not work right now since in is reserved keyword
public stdin is

private stdin0 i64 is intrinsic
module stdin0 i64 is intrinsic

4 changes: 2 additions & 2 deletions src/dev/flang/ast/AbstractFeature.java
Original file line number Diff line number Diff line change
Expand Up @@ -727,7 +727,7 @@ else if (isUniverse())
var p = pos();
var inh = typeFeatureInherits(res);
var typeArg = new Feature(p,
visibility(),
visibility().typeVisibility(),
inh.isEmpty() ? 0 : Consts.MODIFIER_REDEFINE,
selfType(),
FuzionConstants.TYPE_FEATURE_THIS_TYPE,
Expand Down Expand Up @@ -828,7 +828,7 @@ private AbstractFeature existingOrNewTypeFeature(Resolution res, String name, Li
if (result == null)
{
var p = pos();
var typeFeature = new Feature(p, visibility(), 0, NoType.INSTANCE, new List<>(name), typeArgs,
var typeFeature = new Feature(p, visibility().typeVisibility(), 0, NoType.INSTANCE, new List<>(name), typeArgs,
inh,
Contract.EMPTY_CONTRACT,
new Impl(p, new Block(p, new List<>()), Impl.Kind.Routine));
Expand Down
41 changes: 41 additions & 0 deletions src/dev/flang/ast/AbstractType.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,10 @@
package dev.flang.ast;

import java.util.Set;
import java.util.TreeSet;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.stream.Collectors;

import dev.flang.util.ANY;
import dev.flang.util.Errors;
Expand Down Expand Up @@ -67,6 +70,12 @@ public abstract class AbstractType extends ANY implements Comparable<AbstractTyp
private AbstractType _appliedTypePars2Cache;


/**
* Cached result of calling usedFeatures(_usedFeatures).
*/
Set<AbstractFeature> _usedFeatures = null;


/*----------------------------- methods -----------------------------*/


Expand Down Expand Up @@ -1680,6 +1689,38 @@ AbstractType clone(AbstractFeature originalOuterFeature)
return this;
}


/**
* traverse a resolved type collecting all features this type uses.
*
* @param s the features that have already been found
*/
protected abstract void usedFeatures(Set<AbstractFeature> s);


/**
* @param v
*
* @return this type and any of its generics that have more restrictive visibility than `v`.
*/
public Set<AbstractFeature> moreRestrictiveVisibility(Visi v)
{
if (PRECONDITIONS) require
(!v.definesTypeVisibility());

if (_usedFeatures == null)
{
_usedFeatures = new TreeSet<AbstractFeature>();
usedFeatures(_usedFeatures);
}

return _usedFeatures
.stream()
.filter(af -> af.visibility().typeVisibility().ordinal() < v.ordinal())
.collect(Collectors.toSet());
}


}

/* end of file */
42 changes: 42 additions & 0 deletions src/dev/flang/ast/AstErrors.java
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,13 @@ static String s(AbstractAssign a)
{
return ss(a.toString());
}
static String s(Visi v)
{
if (PRECONDITIONS) require
(v != Visi.UNSPECIFIED);

return code(v.toString());
}
static String ss(String s) // statement or expression
{
return expr(s);
Expand Down Expand Up @@ -170,6 +177,10 @@ static String sqn(List<String> names) // names as qualified name "a.b.c"
{
return ss(names.toString("", ".", ""));
}
static String sv(AbstractFeature f)
{
return s(f.visibility()) + " " + s(f);
}
static String code(String s) { return ticksOrNewLine(Terminal.PURPLE + s + Terminal.REGULAR_COLOR); }
static String type(String s) { return ticksOrNewLine(Terminal.YELLOW + s + Terminal.REGULAR_COLOR); }
static String expr(String s) { return ticksOrNewLine(Terminal.CYAN + s + Terminal.REGULAR_COLOR); }
Expand Down Expand Up @@ -1955,6 +1966,37 @@ public static void freeTypeMustNotMaskExistingType(UnresolvedType t, AbstractFea
"To solve this, you may use a different name for free type " + s(t) + ".");
}

public static void calledFeatureInPreconditionHasMoreRestrictiveVisibilityThanFeature(Feature f, AbstractCall c)
{
error(c.pos(), "Called feature in precondition has more restrictive visibility than feature.",
"To solve this, increase the visibility of " + s(c.calledFeature()) + " or do not" +
" use this feature in the precondition."
);
}

public static void illegalVisibilityModifier(Feature f)
{
error(f.pos(), "Feature specifying type visibility does not define a type.",
"To solve this, remove the type visibility: " + s(f.visibility().typeVisibility()) + "."
);
}

public static void argTypeMoreRestrictiveVisbility(Feature f, AbstractFeature arg, Set<AbstractFeature> s)
{
error(f.pos(), "Argument types or any of its generics have more restrictive visibility than feature.",
"To solve this, increase the visibility of " + slbn(s.stream().map(x -> x.featureName()).collect(List.collector())) +
" or specify a different type for the argument " + sbn(arg) + "."
);
}

public static void resultTypeMoreRestrictiveVisibility(Feature f, Set<AbstractFeature> s)
{
error(f.pos(), "Result type or any of its generics have more restrictive visibility than feature.",
"To solve this, increase the visibility of " + slbn(s.stream().map(x -> x.featureName()).collect(List.collector())) +
" or specify a different return type."
);
}

}

/* end of file */
15 changes: 12 additions & 3 deletions src/dev/flang/ast/Feature.java
Original file line number Diff line number Diff line change
Expand Up @@ -101,12 +101,21 @@ public class Feature extends AbstractFeature
* The visibility of this feature
*/
private Visi _visibility;
public Visi visibility() { return _visibility; }
public Visi visibility()
{
return
// NYI anonymous feature should have correct visibility set.
isAnonymousInnerFeature()
? outer().visibility()
: _visibility == Visi.UNSPECIFIED
? Visi.PRIV
: _visibility;
}


/**
* This is used for feature defined using `choice of`
* to set same visibilty for choice elements as for choice in Parser.
* to set same visibility for choice elements as for choice in Parser.
*
* @param v
*/
Expand Down Expand Up @@ -354,7 +363,7 @@ public static Feature anonymous(SourcePosition pos,
Block b)
{
return new Feature(pos,
Visi.PRIV,
Visi.UNSPECIFIED,
0,
r,
new List<String>(FuzionConstants.ANONYMOUS_FEATURE_PREFIX + (uniqueAnonymousFeatureId++)),
Expand Down
4 changes: 4 additions & 0 deletions src/dev/flang/ast/FormalGenerics.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import java.util.Iterator;

import dev.flang.util.ANY;
import dev.flang.util.Errors;
import dev.flang.util.List;
import dev.flang.util.SourcePosition;

Expand Down Expand Up @@ -138,6 +139,9 @@ public boolean errorIfSizeOrTypeDoesNotMatch(List<AbstractType> actualGenerics,
String detail1,
String detail2)
{
if (PRECONDITIONS) require
(Errors.count() > 0 || !actualGenerics.contains(Types.t_ERROR));

boolean result = true;
if (!sizeMatches(actualGenerics))
{
Expand Down
32 changes: 32 additions & 0 deletions src/dev/flang/ast/ResolvedNormalType.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,11 @@

package dev.flang.ast;

import java.util.Set;
import java.util.TreeSet;
import java.util.function.Consumer;
import java.util.stream.Collectors;

import dev.flang.util.Errors;
import dev.flang.util.FuzionConstants;
import dev.flang.util.HasSourcePosition;
Expand Down Expand Up @@ -646,6 +651,33 @@ AbstractFeature originalOuterFeature(AbstractFeature currentOuter)
};
}


/**
* traverse a resolved type collecting all features this type uses.
*
* @param s the features that have already been found
*/
protected void usedFeatures(Set<AbstractFeature> s)
{
// NYI: "This currently does not touch the outer features.
// This means that for a type like (x T).y U the visibility of x and T will be ignored, which is probably wrong."
var f = featureOfType();
if (s.add(f))
{
for (var g : generics())
{
g.usedFeatures(s);
}
if (isChoice())
{
for (var g : choiceGenerics())
{
g.usedFeatures(s);
}
}
}
}

}

/* end of file */
18 changes: 17 additions & 1 deletion src/dev/flang/ast/ResolvedParametricType.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,11 @@
package dev.flang.ast;

import java.util.Set;
import java.util.TreeSet;
import java.util.function.Consumer;
import java.util.stream.Collectors;

import dev.flang.util.Errors;
import dev.flang.util.HasSourcePosition;
import dev.flang.util.List;
import dev.flang.util.SourcePosition;

Expand Down Expand Up @@ -210,6 +212,20 @@ public AbstractType asThis()
}


/**
* traverse a type collecting all features this type uses.
*
* @param s the features that have already been found
*/
protected void usedFeatures(Set<AbstractFeature> s)
{
if (!genericArgument().typeParameter().isTypeFeaturesThisType())
{
genericArgument().typeParameter().resultType().usedFeatures(s);
}
}


/**
* toString
*
Expand Down
15 changes: 15 additions & 0 deletions src/dev/flang/ast/UnresolvedType.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@

package dev.flang.ast;

import java.util.Set;
import java.util.function.Consumer;

import dev.flang.util.Errors;
import dev.flang.util.FuzionConstants;
import dev.flang.util.HasSourcePosition;
Expand Down Expand Up @@ -909,6 +912,18 @@ AbstractType addAsFreeType(Resolution res, AbstractFeature outerfeat)
}



/**
* traverse a type collecting all features this type uses.
*
* @param s the features that have already been found
*/
protected void usedFeatures(Set<AbstractFeature> s)
{
throw new RuntimeException("must not be called on unresolved types.");
}


}

/* end of file */
45 changes: 44 additions & 1 deletion src/dev/flang/ast/Visi.java
Original file line number Diff line number Diff line change
Expand Up @@ -99,14 +99,57 @@ public static Visi from(int ordinal)
{
if (ANY.PRECONDITIONS) ANY.require
(0 <= ordinal,
ordinal < values().length);
ordinal < values().length,
ordinal != UNSPECIFIED.ordinal());

if (ANY.CHECKS) ANY.check
(values()[ordinal].ordinal() == ordinal);

return values()[ordinal];
}

/**
* @return The visibility for features/calls encoded in this.
*/
public Visi featureVisibility()
{
if (this.ordinal() <= PRIVPUB.ordinal())
{
return PRIV;
}
else if (this.ordinal() <= MODPUB.ordinal())
{
return MOD;
}
return PUB;
}


/**
* @return The visibility for types encoded in this.
* PRIV => PRIV, PRIVMOD => MOD, PRIVPUB => PUB, etc.
*/
public Visi typeVisibility()
{
return switch (this)
{
case UNSPECIFIED, PRIV -> Visi.PRIV;
case MOD, PRIVMOD -> Visi.MOD;
case PRIVPUB, MODPUB, PUB -> Visi.PUB;
default -> throw new RuntimeException("undhandled case in Visi.typeVisibility");
};
}


/**
* Does this visibility explicitly specify a different visibility for the type?
* @return
*/
public boolean definesTypeVisibility()
{
return this == Visi.PRIVMOD || this == Visi.PRIVPUB || this == Visi.MODPUB;
}

}

/* end of file */
Loading

0 comments on commit 8b28373

Please sign in to comment.