Skip to content

Commit

Permalink
[error] Restrict use of "this".
Browse files Browse the repository at this point in the history
  • Loading branch information
pfusik committed Nov 14, 2023
1 parent 2afc4f9 commit 5ffab3f
Show file tree
Hide file tree
Showing 16 changed files with 353 additions and 304 deletions.
53 changes: 31 additions & 22 deletions AST.fu
Original file line number Diff line number Diff line change
Expand Up @@ -336,12 +336,6 @@ public class FuScope : FuSymbol

public int Count() => this.Dict.Count;

public FuVar!? FirstParameter()
{
assert this.First is FuVar! result; // FIXME: FuVar!?
return result;
}

public FuContainerType! GetContainer!()
{
for (FuScope!? scope = this; scope != null; scope = scope.Parent) {
Expand Down Expand Up @@ -827,8 +821,12 @@ class FuForeach : FuLoop
{
internal FuExpr# Collection;
public override void AcceptStatement(FuVisitor! visitor) { visitor.VisitForeach(this); }
public FuVar! GetVar() => this.FirstParameter();
public FuVar! GetValueVar() => this.FirstParameter().NextParameter();
public FuVar! GetVar()
{
assert this.First is FuVar! result;
return result;
}
public FuVar! GetValueVar() => this.GetVar().NextVar();
}

class FuIf : FuCondCompletionStatement
Expand Down Expand Up @@ -1057,9 +1055,9 @@ public class FuVar : FuNamedValue
public static FuVar# New(FuType#? type, string name, FuExpr#? defaultValue = null)
=> new FuVar { Type = type, Name = name, Value = defaultValue };
public override void Accept(FuVisitor! visitor, FuPriority parent) { visitor.VisitVar(this); }
public FuVar!? NextParameter()
public FuVar!? NextVar()
{
assert this.Next is FuVar! def;
assert this.Next is FuVar! def; // FIXME: FuVar!?
return def;
}
}
Expand Down Expand Up @@ -1100,23 +1098,30 @@ class FuStaticProperty : FuMember

public class FuMethodBase : FuMember
{
internal bool IsMutator = false;
internal FuParameters() Parameters;
internal bool Throws;
internal FuStatement#? Body;
internal bool IsLive = false;
internal HashSet<FuMethod!>() Calls;
public override bool IsStatic() => false; // constructor
public void AddThis!(FuClass? klass, bool isMutator)
{
FuClassType# type = isMutator ? new FuReadWriteClassType() : new FuClassType();
type.Class = klass;
this.Parameters.Add(FuVar.New(type, "this"));
}
public bool IsMutator() => this.Parameters.First.Type is FuReadWriteClassType;
}

public class FuMethod : FuMethodBase
{
internal FuCallType CallType;
internal FuParameters() Parameters;
internal FuScope() MethodScope;
public static FuMethod# New(FuClass!? klass, FuVisibility visibility, FuCallType callType, FuType# type, FuId id, string name, bool isMutator, FuVar#? param0 = null, FuVar#? param1 = null, FuVar#? param2 = null, FuVar#? param3 = null)
public static FuMethod# New(FuClass? klass, FuVisibility visibility, FuCallType callType, FuType# type, FuId id, string name, bool isMutator, FuVar#? param0 = null, FuVar#? param1 = null, FuVar#? param2 = null, FuVar#? param3 = null)
{
FuMethod# result = new FuMethod { Visibility = visibility, CallType = callType, Type = type, Id = id, Name = name };
result.IsMutator = isMutator;
if (callType != FuCallType.Static)
result.AddThis(klass, isMutator);
if (param0 != null) {
result.Parameters.Add(param0);
if (param1 != null) {
Expand All @@ -1132,6 +1137,16 @@ public class FuMethod : FuMethodBase
}
public override bool IsStatic() => this.CallType == FuCallType.Static;
public bool IsAbstractOrVirtual() => this.CallType == FuCallType.Abstract || this.CallType == FuCallType.Virtual;
public FuVar!? FirstParameter()
{
assert this.Parameters.First is FuVar! first; // FIXME: FuVar!?
return IsStatic() ? first : first.NextVar();
}
public int GetParametersCount()
{
int c = this.Parameters.Count();
return IsStatic() ? c : c - 1;
}
public FuMethod GetDeclaringMethod()
{
FuMethod method = this;
Expand All @@ -1141,7 +1156,6 @@ public class FuMethod : FuMethodBase
}
return method;
}
public bool IsToString() => this.Name == "ToString" && this.CallType != FuCallType.Static && this.Parameters.Count() == 0;
}

class FuMethodGroup : FuMember
Expand Down Expand Up @@ -1210,11 +1224,6 @@ public class FuClass : FuContainerType
return false;
}

public FuClass()
{
Add(FuVar.New(new FuReadWriteClassType { Class = this }, "this")); // shadows "this" in base class
}

public static FuClass# New(FuCallType callType, FuId id, string name, int typeParameterCount = 0)
=> new FuClass { CallType = callType, Id = id, Name = name, TypeParameterCount = typeParameterCount };

Expand All @@ -1238,9 +1247,9 @@ public class FuClass : FuContainerType
return true;
}

public bool HasToString() => TryLookup("ToString", false) is FuMethod method && method.IsToString();
public bool HasToString() => TryLookup("ToString", false) is FuMethod method && method.Id == FuId.ClassToString;

public bool AddsToString() => this.Dict.ContainsKey("ToString") && this.Dict["ToString"] is FuMethod method && method.IsToString()
public bool AddsToString() => this.Dict.ContainsKey("ToString") && this.Dict["ToString"] is FuMethod method && method.Id == FuId.ClassToString
&& method.CallType != FuCallType.Override && method.CallType != FuCallType.Sealed;
}

Expand Down
10 changes: 4 additions & 6 deletions GenBase.fu
Original file line number Diff line number Diff line change
Expand Up @@ -429,7 +429,7 @@ public abstract class GenBase : FuVisitor
protected void WriteParametersDoc!(FuMethod method)
{
bool first = true;
for (FuVar? param = method.Parameters.FirstParameter(); param != null; param = param.NextParameter()) {
for (FuVar? param = method.FirstParameter(); param != null; param = param.NextVar()) {
if (param.Documentation != null) {
WriteParameterDoc(param, first);
first = false;
Expand Down Expand Up @@ -697,14 +697,14 @@ public abstract class GenBase : FuVisitor

protected void WriteArgs!(FuMethod method, List<FuExpr#> args)
{
FuVar param = method.Parameters.FirstParameter();
FuVar param = method.FirstParameter();
bool first = true;
foreach (FuExpr arg in args) {
if (!first)
Write(", ");
first = false;
WriteStronglyCoerced(param.Type, arg);
param = param.NextParameter();
param = param.NextVar();
}
}

Expand Down Expand Up @@ -1884,7 +1884,7 @@ public abstract class GenBase : FuVisitor

protected void WriteRemainingParameters!(FuMethod method, bool first, bool defaultArguments)
{
for (FuVar? param = method.Parameters.FirstParameter(); param != null; param = param.NextParameter()) {
for (FuVar? param = method.FirstParameter(); param != null; param = param.NextVar()) {
if (!first)
Write(", ");
first = false;
Expand Down Expand Up @@ -1995,8 +1995,6 @@ public abstract class GenBase : FuVisitor
this.SwitchesWithGoto.Clear();
this.CurrentTemporaries.Clear();
break;
case FuVar _: // "this"
break;
default:
assert false;
}
Expand Down
10 changes: 5 additions & 5 deletions GenC.fu
Original file line number Diff line number Diff line change
Expand Up @@ -937,12 +937,12 @@ public class GenC : GenCCpp
WriteStorageTemporary(call.Method.Left);
}
assert call.Method.Symbol is FuMethod method;
FuVar? param = method.Parameters.FirstParameter();
FuVar? param = method.FirstParameter();
foreach (FuExpr arg in call.Arguments) {
WriteCTemporaries(arg);
if (call.Method.Symbol.Id != FuId.ConsoleWrite && call.Method.Symbol.Id != FuId.ConsoleWriteLine && !(param.Type is FuStorageType))
WriteStorageTemporary(arg);
param = param.NextParameter();
param = param.NextVar();
}
break;
default:
Expand Down Expand Up @@ -1635,7 +1635,7 @@ public class GenC : GenCCpp
void WriteArgsAndRightParenthesis!(FuMethod method, List<FuExpr#> args)
{
int i = 0;
for (FuVar? param = method.Parameters.FirstParameter(); param != null; param = param.NextParameter()) {
for (FuVar? param = method.FirstParameter(); param != null; param = param.NextVar()) {
if (i > 0 || method.CallType != FuCallType.Static)
Write(", ");
if (i >= args.Count)
Expand Down Expand Up @@ -2883,7 +2883,7 @@ public class GenC : GenCCpp
void WriteInstanceParameters!(FuMethod method)
{
WriteChar('(');
if (!method.IsMutator)
if (!method.IsMutator())
Write("const ");
WriteName(method.Parent);
Write(" *self");
Expand Down Expand Up @@ -3235,7 +3235,7 @@ public class GenC : GenCCpp
}
else {
WriteSignature(method);
for (FuVar? param = method.Parameters.FirstParameter(); param != null; param = param.NextParameter()) {
for (FuVar? param = method.FirstParameter(); param != null; param = param.NextVar()) {
if (NeedToDestruct(param))
this.VarsToDestruct.Add(param);
}
Expand Down
2 changes: 1 addition & 1 deletion GenCpp.fu
Original file line number Diff line number Diff line change
Expand Up @@ -1721,7 +1721,7 @@ public class GenCpp : GenCCpp
void WriteParametersAndConst!(FuMethod method, bool defaultArguments)
{
WriteParameters(method, defaultArguments);
if (method.CallType != FuCallType.Static && !method.IsMutator)
if (method.CallType != FuCallType.Static && !method.IsMutator())
Write(" const");
}

Expand Down
2 changes: 0 additions & 2 deletions GenD.fu
Original file line number Diff line number Diff line change
Expand Up @@ -1423,8 +1423,6 @@ public class GenD : GenCCppD
WriteMethod(method);
this.CurrentTemporaries.Clear();
break;
case FuVar _: // "this"
break;
default:
assert false;
}
Expand Down
14 changes: 7 additions & 7 deletions GenJava.fu
Original file line number Diff line number Diff line change
Expand Up @@ -1282,12 +1282,12 @@ public class GenJava : GenTyped
if (method.Id == FuId.Main && paramCount == 0)
Write("String[] args");
else {
FuVar param = method.Parameters.FirstParameter();
FuVar param = method.FirstParameter();
for (int i = 0; i < paramCount; i++) {
if (i > 0)
Write(", ");
WriteTypeAndName(param);
param = param.NextParameter();
param = param.NextVar();
}
}
WriteChar(')');
Expand All @@ -1297,7 +1297,7 @@ public class GenJava : GenTyped

void WriteOverloads!(FuMethod method, int paramCount)
{
if (paramCount + 1 < method.Parameters.Count())
if (paramCount + 1 < method.GetParametersCount())
WriteOverloads(method, paramCount + 1);
WriteSignature(method, paramCount);
WriteNewLine();
Expand All @@ -1306,11 +1306,11 @@ public class GenJava : GenTyped
Write("return ");
WriteName(method);
WriteChar('(');
FuVar param = method.Parameters.FirstParameter();
FuVar param = method.FirstParameter();
for (int i = 0; i < paramCount; i++) {
WriteName(param);
Write(", ");
param = param.NextParameter();
param = param.NextVar();
}
param.Value.Accept(this, FuPriority.Argument);
WriteLine(");");
Expand Down Expand Up @@ -1339,10 +1339,10 @@ public class GenJava : GenTyped

protected override void WriteMethod!(FuMethod method)
{
WriteSignature(method, method.Parameters.Count());
WriteSignature(method, method.GetParametersCount());
WriteBody(method);
int i = 0;
for (FuVar? param = method.Parameters.FirstParameter(); param != null; param = param.NextParameter()) {
for (FuVar? param = method.FirstParameter(); param != null; param = param.NextVar()) {
if (param.Value != null) {
WriteOverloads(method, i);
break;
Expand Down
2 changes: 1 addition & 1 deletion GenSwift.fu
Original file line number Diff line number Diff line change
Expand Up @@ -1620,7 +1620,7 @@ public class GenSwift : GenPySwift
if (method.CallType == FuCallType.Abstract)
WriteLine("preconditionFailure(\"Abstract method called\")");
else {
for (FuVar? param = method.Parameters.FirstParameter(); param != null; param = param.NextParameter()) {
for (FuVar? param = method.FirstParameter(); param != null; param = param.NextVar()) {
if (param.IsAssigned) {
Write("var ");
WriteTypeAndName(param);
Expand Down
2 changes: 1 addition & 1 deletion GenTs.fu
Original file line number Diff line number Diff line change
Expand Up @@ -268,7 +268,7 @@ public class GenTs : GenJs
WriteName(method);
WriteChar('(');
int i = 0;
for (FuVar? param = method.Parameters.FirstParameter(); param != null; param = param.NextParameter()) {
for (FuVar? param = method.FirstParameter(); param != null; param = param.NextVar()) {
if (i > 0)
Write(", ");
WriteName(param);
Expand Down
14 changes: 8 additions & 6 deletions Parser.fu
Original file line number Diff line number Diff line change
Expand Up @@ -847,10 +847,12 @@ public class FuParser : FuLexer
}
}

void ParseMethod!(FuMethod! method)
void ParseMethod!(FuClass! klass, FuMethod# method)
{
AddSymbol(klass, method);
method.Parameters.Parent = klass;
if (method.CallType != FuCallType.Static)
method.IsMutator = Eat(FuToken.ExclamationMark);
method.AddThis(klass, Eat(FuToken.ExclamationMark));
ExpectOrSkip(FuToken.LeftParenthesis);
if (!See(FuToken.RightParenthesis)) {
do {
Expand Down Expand Up @@ -944,7 +946,9 @@ public class FuParser : FuLexer
if (visibility == FuVisibility.Private)
visibility = FuVisibility.Internal; // TODO
klass.Constructor = new FuMethodBase { Line = call.Line, Documentation = doc, Visibility = visibility, Parent = klass,
Type = this.Program.System.VoidType, Name = klass.Name, IsMutator = true, Body = ParseBlock() };
Type = this.Program.System.VoidType, Name = klass.Name, Body = ParseBlock() };
klass.Constructor.Parameters.Parent = klass;
klass.Constructor.AddThis(klass, true);
continue;
}

Expand Down Expand Up @@ -977,9 +981,7 @@ public class FuParser : FuLexer
ReportError($"{CallTypeToString(callType)} method cannot be private");

FuMethod# method = new FuMethod { Line = line, Documentation = doc, Visibility = visibility, CallType = callType, TypeExpr = type, Name = name };
AddSymbol(klass, method);
method.Parameters.Parent = klass;
ParseMethod(method);
ParseMethod(klass, method);
continue;
}

Expand Down
Loading

0 comments on commit 5ffab3f

Please sign in to comment.