Skip to content

Commit

Permalink
перенос проверок функции статическим анализом
Browse files Browse the repository at this point in the history
  • Loading branch information
Stepami committed Feb 16, 2024
1 parent 2d619e1 commit 377b417
Show file tree
Hide file tree
Showing 5 changed files with 64 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ namespace Interpreter.Lib.IR.Ast.Impl.Nodes.Declarations.AfterTypesAreLoaded;

public class FunctionDeclaration : AfterTypesAreLoadedDeclaration
{
private IReadOnlyCollection<ReturnStatement> _returnStatements;

public IdentifierReference Name { get; }
public TypeValue ReturnTypeValue { get; }
public List<PropertyTypeValue> Arguments { get; }
Expand All @@ -33,10 +35,17 @@ public FunctionDeclaration(
Statements.Parent = this;
}

public bool HasReturnStatement() =>
Statements.GetAllNodes()
public bool HasReturnStatement()
{
_returnStatements ??= GetReturnStatements();
return _returnStatements.Count > 0;
}

public IReadOnlyCollection<ReturnStatement> GetReturnStatements() =>
_returnStatements ??= Statements
.GetAllNodes()
.OfType<ReturnStatement>()
.Any();
.ToArray();

public override IEnumerator<AbstractSyntaxTreeNode> GetEnumerator()
{
Expand Down
3 changes: 3 additions & 0 deletions Interpreter.Lib/IR/CheckSemantics/Types/FunctionType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ public FunctionType(Type returnType, IEnumerable<Type> arguments)
_arguments = new List<Type>(arguments);
}

public void DefineReturnType(Type returnType) =>
ReturnType = returnType;

public override void ResolveReference(
Type reference,
string refId,
Expand Down
42 changes: 41 additions & 1 deletion Interpreter.Lib/IR/CheckSemantics/Visitors/SemanticChecker.cs
Original file line number Diff line number Diff line change
Expand Up @@ -374,6 +374,46 @@ symbol as FunctionSymbol

public FunctionType Visit(FunctionDeclaration visitable)
{
throw new NotImplementedException();
var symbol =
visitable.SymbolTable.FindSymbol<FunctionSymbol>(visitable.Name)
?? throw new UnknownIdentifierReference(visitable.Name);

_storage.RemoveIfPresent(symbol);

visitable.Statements.Accept(this);

var returnStatements = visitable.GetReturnStatements()
.Select(x => new
{
Statement = x,
Type = x.Accept(this)
});
Type undefined = "undefined";
if (symbol.Type.ReturnType.Equals(undefined))
{
var returnStatementsGroups = returnStatements
.GroupBy(x => x.Type)
.ToList();
if (returnStatementsGroups.Count > 1)
throw new CannotDefineType(visitable.Segment);
symbol.Type.DefineReturnType(returnStatementsGroups[0].Key);
}
else
{
var wrongReturn = returnStatements
.FirstOrDefault(x => !x.Type.Equals(symbol.Type.ReturnType));
if (wrongReturn is not null)
throw new WrongReturnType(
wrongReturn.Statement.Segment,
expected: symbol.Type.ReturnType,
actual: wrongReturn.Type);
}

Type @void = "void";
var hasReturnStatement = visitable.HasReturnStatement();
if (!symbol.Type.Equals(@void) && !hasReturnStatement)
throw new FunctionWithoutReturnStatement(visitable.Statements.Segment);

return symbol.Type;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,7 @@ public interface IFunctionWithUndefinedReturnStorage

FunctionDeclaration Get(FunctionSymbol symbol);

void RemoveIfPresent(FunctionSymbol symbol);

IEnumerable<FunctionDeclaration> Flush();
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,12 @@ public FunctionDeclaration Get(FunctionSymbol symbol)
return declaration;
}

public void RemoveIfPresent(FunctionSymbol symbol)
{
_declarations.Remove(symbol.Id);
_keysWithOrder.Remove(symbol.Id);
}

public IEnumerable<FunctionDeclaration> Flush() => _declarations
.OrderBy(kvp => _keysWithOrder[kvp.Key])
.Select(x =>
Expand Down

0 comments on commit 377b417

Please sign in to comment.