From ca57c6964cb384132ef27a461dc3fba6134a656c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=A1=D1=82=D0=B5=D0=BF=D0=B0=D0=BD?= Date: Fri, 26 Jul 2024 18:42:40 +0300 Subject: [PATCH] =?UTF-8?q?#59=20-=20=D0=BF=D0=B5=D1=80=D0=B5=D1=85=D0=BE?= =?UTF-8?q?=D0=B4=20=D0=BD=D0=B0=20IReadOnlyList=20(#70)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * #31 - change nullability of Parent * #31 unbound ast node from segment * #59 - переход на IReadOnlyList --- .../FrontEnd/GetTokens/Data/Token.cs | 3 ++ .../FrontEnd/TopDownParse/Impl/Parser.cs | 5 ++- .../IR/Ast/AbstractSyntaxTreeNode.cs | 40 ++++++++++--------- .../FunctionDeclaration.cs | 21 ++++------ .../AfterTypesAreLoaded/LexicalDeclaration.cs | 12 +++--- .../Nodes/Declarations/TypeDeclaration.cs | 20 ++-------- .../AccessExpressions/DotAccess.cs | 12 ++---- .../AccessExpressions/IndexAccess.cs | 12 ++---- .../Nodes/Expressions/AssignmentExpression.cs | 9 ++--- .../Nodes/Expressions/BinaryExpression.cs | 9 ++--- .../Impl/Nodes/Expressions/CallExpression.cs | 27 +++++-------- .../Nodes/Expressions/CastAsExpression.cs | 8 ++-- .../ComplexLiterals/ArrayLiteral.cs | 14 ++++--- .../ComplexLiterals/ObjectLiteral.cs | 14 ++++--- .../Expressions/ComplexLiterals/Property.cs | 9 ++--- .../Expressions/ConditionalExpression.cs | 10 ++--- .../Nodes/Expressions/MemberExpression.cs | 28 +++++-------- .../PrimaryExpressions/PrimaryExpression.cs | 5 --- .../Impl/Nodes/Expressions/UnaryExpression.cs | 8 ++-- .../IR/Ast/Impl/Nodes/ScriptBody.cs | 15 ++++--- .../Impl/Nodes/Statements/BlockStatement.cs | 14 ++++--- .../Nodes/Statements/ExpressionStatement.cs | 10 ++--- .../Ast/Impl/Nodes/Statements/IfStatement.cs | 23 +++++------ .../Nodes/Statements/InsideStatementJump.cs | 5 --- .../Impl/Nodes/Statements/ReturnStatement.cs | 13 ++---- .../Impl/Nodes/Statements/WhileStatement.cs | 9 ++--- .../IR/Ast/Visitors/InstructionProvider.cs | 11 +++-- .../Exceptions/ArrayAccessException.cs | 9 ++--- .../Exceptions/AssignmentToConst.cs | 7 +--- .../Exceptions/CannotDefineType.cs | 7 +--- .../Exceptions/ConstWithoutInitializer.cs | 7 +--- .../Exceptions/DeclarationAlreadyExists.cs | 7 +--- .../FunctionWithoutReturnStatement.cs | 8 +--- .../Exceptions/IncompatibleTypesOfOperands.cs | 8 +--- .../Exceptions/NonAccessibleType.cs | 7 +--- .../Exceptions/NotBooleanTestExpression.cs | 8 +--- .../Exceptions/ObjectAccessException.cs | 8 +--- .../Exceptions/OutsideOfStatement.cs | 8 +--- .../Exceptions/ReturnOutsideFunction.cs | 8 +--- .../Exceptions/SemanticException.cs | 25 +++++++----- .../Exceptions/SymbolIsNotCallable.cs | 8 +--- .../Exceptions/UnknownIdentifierReference.cs | 7 +--- .../Exceptions/UnsupportedOperation.cs | 8 +--- .../WrongArrayLiteralDeclaration.cs | 10 ++--- .../Exceptions/WrongAssignmentTarget.cs | 9 ++--- .../Exceptions/WrongConditionalTypes.cs | 14 ++++--- .../Exceptions/WrongNumberOfArguments.cs | 10 ++--- .../Exceptions/WrongReturnType.cs | 10 ++--- .../Exceptions/WrongTypeOfArgument.cs | 10 ++--- .../Visitors/DeclarationVisitor.cs | 9 +++-- .../Visitors/SemanticChecker.cs | 17 ++++---- .../Impl/SymbolTableInitializerService.cs | 4 +- .../Visitors/SymbolTableInitializer.cs | 11 +++-- .../Visitors/TypeSystemLoader.cs | 7 ++-- .../HydraScript.Tests/Unit/IR/AstNodeTests.cs | 10 ++--- 55 files changed, 256 insertions(+), 371 deletions(-) diff --git a/src/HydraScript.Lib/FrontEnd/GetTokens/Data/Token.cs b/src/HydraScript.Lib/FrontEnd/GetTokens/Data/Token.cs index 2e614cde..3d007a73 100644 --- a/src/HydraScript.Lib/FrontEnd/GetTokens/Data/Token.cs +++ b/src/HydraScript.Lib/FrontEnd/GetTokens/Data/Token.cs @@ -31,6 +31,9 @@ public record Segment(Coordinates Start, Coordinates End) public static Segment operator +(Segment left, Segment right) => new(left.Start, right.End); + + public static implicit operator string(Segment segment) => + segment.ToString(); } [ExcludeFromCodeCoverage] diff --git a/src/HydraScript.Lib/FrontEnd/TopDownParse/Impl/Parser.cs b/src/HydraScript.Lib/FrontEnd/TopDownParse/Impl/Parser.cs index aee920f8..14e9e840 100644 --- a/src/HydraScript.Lib/FrontEnd/TopDownParse/Impl/Parser.cs +++ b/src/HydraScript.Lib/FrontEnd/TopDownParse/Impl/Parser.cs @@ -492,7 +492,10 @@ private Expression ConditionalExpression() var consequent = Expression(); Expect("Colon"); var alternate = Expression(); - return new ConditionalExpression(test, consequent, alternate); + return new ConditionalExpression(test, consequent, alternate) + { + Segment = consequent.Segment + alternate.Segment + }; } return test; diff --git a/src/HydraScript.Lib/IR/Ast/AbstractSyntaxTreeNode.cs b/src/HydraScript.Lib/IR/Ast/AbstractSyntaxTreeNode.cs index b4ef320e..fa4eed5a 100644 --- a/src/HydraScript.Lib/IR/Ast/AbstractSyntaxTreeNode.cs +++ b/src/HydraScript.Lib/IR/Ast/AbstractSyntaxTreeNode.cs @@ -1,29 +1,38 @@ using System.Collections; -using HydraScript.Lib.FrontEnd.GetTokens.Data; using HydraScript.Lib.IR.CheckSemantics.Variables; namespace HydraScript.Lib.IR.Ast; public abstract class AbstractSyntaxTreeNode : - IEnumerable, + IReadOnlyList, IVisitable { - public AbstractSyntaxTreeNode? Parent { get; set; } + public AbstractSyntaxTreeNode Parent { get; set; } = default!; + + protected virtual bool IsRoot => false; public SymbolTable SymbolTable { get; set; } = default!; - public Segment Segment { get; init; } = default!; + public string Segment { get; init; } = string.Empty; + + protected virtual IReadOnlyList Children { get; } = []; + + public IEnumerator GetEnumerator() => + Children.ToList().GetEnumerator(); + + IEnumerator IEnumerable.GetEnumerator() => + GetEnumerator(); + + public int Count => Children.Count; + + public AbstractSyntaxTreeNode this[int index] => + Children[index]; internal List GetAllNodes() { - var result = new List - { - this - }; - foreach (var child in this) - { - result.AddRange(child.GetAllNodes()); - } + List result = [this]; + for (var index = 0; index < Children.Count; index++) + result.AddRange(Children[index].GetAllNodes()); return result; } @@ -31,7 +40,7 @@ internal List GetAllNodes() public bool ChildOf() where T : AbstractSyntaxTreeNode { var parent = Parent; - while (parent != null) + while (!parent.IsRoot) { if (parent is T) { @@ -44,11 +53,6 @@ public bool ChildOf() where T : AbstractSyntaxTreeNode return false; } - public abstract IEnumerator GetEnumerator(); - - IEnumerator IEnumerable.GetEnumerator() => - GetEnumerator(); - public virtual TReturn Accept(IVisitor visitor) => visitor.DefaultVisit; diff --git a/src/HydraScript.Lib/IR/Ast/Impl/Nodes/Declarations/AfterTypesAreLoaded/FunctionDeclaration.cs b/src/HydraScript.Lib/IR/Ast/Impl/Nodes/Declarations/AfterTypesAreLoaded/FunctionDeclaration.cs index 947e7ced..0d2c02e3 100644 --- a/src/HydraScript.Lib/IR/Ast/Impl/Nodes/Declarations/AfterTypesAreLoaded/FunctionDeclaration.cs +++ b/src/HydraScript.Lib/IR/Ast/Impl/Nodes/Declarations/AfterTypesAreLoaded/FunctionDeclaration.cs @@ -6,7 +6,7 @@ namespace HydraScript.Lib.IR.Ast.Impl.Nodes.Declarations.AfterTypesAreLoaded; [AutoVisitable] public partial class FunctionDeclaration : AfterTypesAreLoadedDeclaration { - private IReadOnlyCollection? _returnStatements; + protected override IReadOnlyList Children => [Statements]; public IdentifierReference Name { get; } public TypeValue ReturnTypeValue { get; } @@ -25,25 +25,18 @@ public FunctionDeclaration( Statements = blockStatement; Statements.Parent = this; - } - - public bool HasReturnStatement() - { - _returnStatements ??= GetReturnStatements(); - return _returnStatements.Count > 0; - } - public IReadOnlyCollection GetReturnStatements() => - _returnStatements ??= Statements + ReturnStatements = Statements .GetAllNodes() .OfType() .ToArray(); - - public override IEnumerator GetEnumerator() - { - yield return Statements; } + public bool HasReturnStatement() => + ReturnStatements.Count > 0; + + public IReadOnlyCollection ReturnStatements { get; } + protected override string NodeRepresentation() => "function " + Name; } \ No newline at end of file diff --git a/src/HydraScript.Lib/IR/Ast/Impl/Nodes/Declarations/AfterTypesAreLoaded/LexicalDeclaration.cs b/src/HydraScript.Lib/IR/Ast/Impl/Nodes/Declarations/AfterTypesAreLoaded/LexicalDeclaration.cs index 4374f6d9..aa38d093 100644 --- a/src/HydraScript.Lib/IR/Ast/Impl/Nodes/Declarations/AfterTypesAreLoaded/LexicalDeclaration.cs +++ b/src/HydraScript.Lib/IR/Ast/Impl/Nodes/Declarations/AfterTypesAreLoaded/LexicalDeclaration.cs @@ -5,18 +5,20 @@ namespace HydraScript.Lib.IR.Ast.Impl.Nodes.Declarations.AfterTypesAreLoaded; [AutoVisitable] public partial class LexicalDeclaration(bool readOnly) : AfterTypesAreLoadedDeclaration { + private readonly List _assignments = []; + protected override IReadOnlyList Children => + _assignments; + public bool ReadOnly { get; } = readOnly; - public List Assignments { get; } = []; + public IReadOnlyList Assignments => + _assignments; public void AddAssignment(AssignmentExpression assignment) { assignment.Parent = this; - Assignments.Add(assignment); + _assignments.Add(assignment); } - public override IEnumerator GetEnumerator() => - Assignments.GetEnumerator(); - protected override string NodeRepresentation() => ReadOnly ? "const" : "let"; } \ No newline at end of file diff --git a/src/HydraScript.Lib/IR/Ast/Impl/Nodes/Declarations/TypeDeclaration.cs b/src/HydraScript.Lib/IR/Ast/Impl/Nodes/Declarations/TypeDeclaration.cs index aef76c8e..cca75678 100644 --- a/src/HydraScript.Lib/IR/Ast/Impl/Nodes/Declarations/TypeDeclaration.cs +++ b/src/HydraScript.Lib/IR/Ast/Impl/Nodes/Declarations/TypeDeclaration.cs @@ -3,25 +3,13 @@ namespace HydraScript.Lib.IR.Ast.Impl.Nodes.Declarations; [AutoVisitable] -public partial class TypeDeclaration : Declaration +public partial class TypeDeclaration(IdentifierReference typeId, TypeValue typeValue) : Declaration { - private readonly TypeValue _typeValue; - public IdentifierReference TypeId { get; } - - public TypeDeclaration(IdentifierReference typeId, TypeValue typeValue) - { - TypeId = typeId; - _typeValue = typeValue; - } + public IdentifierReference TypeId { get; } = typeId; public Type BuildType() => - _typeValue.BuildType(SymbolTable); - - public override IEnumerator GetEnumerator() - { - yield break; - } + typeValue.BuildType(SymbolTable); protected override string NodeRepresentation() => - $"type {TypeId.Name} = {_typeValue}"; + $"type {TypeId.Name} = {typeValue}"; } \ No newline at end of file diff --git a/src/HydraScript.Lib/IR/Ast/Impl/Nodes/Expressions/AccessExpressions/DotAccess.cs b/src/HydraScript.Lib/IR/Ast/Impl/Nodes/Expressions/AccessExpressions/DotAccess.cs index bb9094ac..94054711 100644 --- a/src/HydraScript.Lib/IR/Ast/Impl/Nodes/Expressions/AccessExpressions/DotAccess.cs +++ b/src/HydraScript.Lib/IR/Ast/Impl/Nodes/Expressions/AccessExpressions/DotAccess.cs @@ -5,6 +5,9 @@ namespace HydraScript.Lib.IR.Ast.Impl.Nodes.Expressions.AccessExpressions; [AutoVisitable] public partial class DotAccess : AccessExpression { + protected override IReadOnlyList Children => + HasNext() ? [Property, Next!] : [Property]; + public IdentifierReference Property { get; } public DotAccess(IdentifierReference property, AccessExpression? prev = null) : base(prev) @@ -13,14 +16,5 @@ public DotAccess(IdentifierReference property, AccessExpression? prev = null) : Property.Parent = this; } - public override IEnumerator GetEnumerator() - { - yield return Property; - if (HasNext()) - { - yield return Next!; - } - } - protected override string NodeRepresentation() => "."; } \ No newline at end of file diff --git a/src/HydraScript.Lib/IR/Ast/Impl/Nodes/Expressions/AccessExpressions/IndexAccess.cs b/src/HydraScript.Lib/IR/Ast/Impl/Nodes/Expressions/AccessExpressions/IndexAccess.cs index 4216f2b6..1a74d2a0 100644 --- a/src/HydraScript.Lib/IR/Ast/Impl/Nodes/Expressions/AccessExpressions/IndexAccess.cs +++ b/src/HydraScript.Lib/IR/Ast/Impl/Nodes/Expressions/AccessExpressions/IndexAccess.cs @@ -3,6 +3,9 @@ namespace HydraScript.Lib.IR.Ast.Impl.Nodes.Expressions.AccessExpressions; [AutoVisitable] public partial class IndexAccess : AccessExpression { + protected override IReadOnlyList Children => + HasNext() ? [Index, Next!] : [Index]; + public Expression Index { get; } public IndexAccess(Expression index, AccessExpression? prev = null) : base(prev) @@ -11,14 +14,5 @@ public IndexAccess(Expression index, AccessExpression? prev = null) : base(prev) Index.Parent = this; } - public override IEnumerator GetEnumerator() - { - yield return Index; - if (HasNext()) - { - yield return Next!; - } - } - protected override string NodeRepresentation() => "[]"; } \ No newline at end of file diff --git a/src/HydraScript.Lib/IR/Ast/Impl/Nodes/Expressions/AssignmentExpression.cs b/src/HydraScript.Lib/IR/Ast/Impl/Nodes/Expressions/AssignmentExpression.cs index d41f5f2d..4e5e0966 100644 --- a/src/HydraScript.Lib/IR/Ast/Impl/Nodes/Expressions/AssignmentExpression.cs +++ b/src/HydraScript.Lib/IR/Ast/Impl/Nodes/Expressions/AssignmentExpression.cs @@ -5,6 +5,9 @@ namespace HydraScript.Lib.IR.Ast.Impl.Nodes.Expressions; [AutoVisitable] public partial class AssignmentExpression : Expression { + protected override IReadOnlyList Children => + [Destination, Source]; + public LeftHandSideExpression Destination { get; } public Expression Source { get; } public TypeValue? DestinationType { get; } @@ -23,11 +26,5 @@ public AssignmentExpression( DestinationType = destinationType; } - public override IEnumerator GetEnumerator() - { - yield return Destination; - yield return Source; - } - protected override string NodeRepresentation() => "="; } \ No newline at end of file diff --git a/src/HydraScript.Lib/IR/Ast/Impl/Nodes/Expressions/BinaryExpression.cs b/src/HydraScript.Lib/IR/Ast/Impl/Nodes/Expressions/BinaryExpression.cs index bbebf623..0acb152a 100644 --- a/src/HydraScript.Lib/IR/Ast/Impl/Nodes/Expressions/BinaryExpression.cs +++ b/src/HydraScript.Lib/IR/Ast/Impl/Nodes/Expressions/BinaryExpression.cs @@ -3,6 +3,9 @@ namespace HydraScript.Lib.IR.Ast.Impl.Nodes.Expressions; [AutoVisitable] public partial class BinaryExpression : Expression { + protected override IReadOnlyList Children => + [Left, Right]; + public Expression Left { get; } public string Operator { get; } public Expression Right { get; } @@ -18,11 +21,5 @@ public BinaryExpression(Expression left, string @operator, Expression right) Right.Parent = this; } - public override IEnumerator GetEnumerator() - { - yield return Left; - yield return Right; - } - protected override string NodeRepresentation() => Operator; } \ No newline at end of file diff --git a/src/HydraScript.Lib/IR/Ast/Impl/Nodes/Expressions/CallExpression.cs b/src/HydraScript.Lib/IR/Ast/Impl/Nodes/Expressions/CallExpression.cs index dca0bb29..eeb07276 100644 --- a/src/HydraScript.Lib/IR/Ast/Impl/Nodes/Expressions/CallExpression.cs +++ b/src/HydraScript.Lib/IR/Ast/Impl/Nodes/Expressions/CallExpression.cs @@ -5,33 +5,26 @@ namespace HydraScript.Lib.IR.Ast.Impl.Nodes.Expressions; [AutoVisitable] public partial class CallExpression : LeftHandSideExpression { + private readonly List _parameters; + + protected override IReadOnlyList Children => + [Member, .._parameters]; + public MemberExpression Member { get; } - public List Parameters { get; } + public IReadOnlyList Parameters => _parameters; public CallExpression(MemberExpression member, IEnumerable expressions) { Member = member; Member.Parent = this; - Parameters = new List(expressions); - Parameters.ForEach(expr => expr.Parent = this); + _parameters = new List(expressions); + _parameters.ForEach(expr => expr.Parent = this); } - public override IdentifierReference Id => - Member.Id; - - public override bool Empty() => - Member.Empty(); + public override IdentifierReference Id => Member.Id; - public override IEnumerator GetEnumerator() - { - var nodes = new List - { - Member - }; - nodes.AddRange(Parameters); - return nodes.GetEnumerator(); - } + public override bool Empty() => Member.Empty(); protected override string NodeRepresentation() => "()"; } \ No newline at end of file diff --git a/src/HydraScript.Lib/IR/Ast/Impl/Nodes/Expressions/CastAsExpression.cs b/src/HydraScript.Lib/IR/Ast/Impl/Nodes/Expressions/CastAsExpression.cs index 4cf1e118..72ed955b 100644 --- a/src/HydraScript.Lib/IR/Ast/Impl/Nodes/Expressions/CastAsExpression.cs +++ b/src/HydraScript.Lib/IR/Ast/Impl/Nodes/Expressions/CastAsExpression.cs @@ -5,6 +5,9 @@ namespace HydraScript.Lib.IR.Ast.Impl.Nodes.Expressions; [AutoVisitable] public partial class CastAsExpression : Expression { + protected override IReadOnlyList Children => + [Expression]; + public Expression Expression { get; } public TypeValue Cast { get; } @@ -16,10 +19,5 @@ public CastAsExpression(Expression expression, TypeValue cast) Cast = cast; } - public override IEnumerator GetEnumerator() - { - yield return Expression; - } - protected override string NodeRepresentation() => $"as {Cast}"; } \ No newline at end of file diff --git a/src/HydraScript.Lib/IR/Ast/Impl/Nodes/Expressions/ComplexLiterals/ArrayLiteral.cs b/src/HydraScript.Lib/IR/Ast/Impl/Nodes/Expressions/ComplexLiterals/ArrayLiteral.cs index 2b301e6c..6c96ca32 100644 --- a/src/HydraScript.Lib/IR/Ast/Impl/Nodes/Expressions/ComplexLiterals/ArrayLiteral.cs +++ b/src/HydraScript.Lib/IR/Ast/Impl/Nodes/Expressions/ComplexLiterals/ArrayLiteral.cs @@ -3,16 +3,18 @@ namespace HydraScript.Lib.IR.Ast.Impl.Nodes.Expressions.ComplexLiterals; [AutoVisitable] public partial class ArrayLiteral : ComplexLiteral { - public List Expressions { get; } + private readonly List _expressions; + + protected override IReadOnlyList Children => + _expressions; + + public IReadOnlyList Expressions => _expressions; public ArrayLiteral(IEnumerable expressions) { - Expressions = new List(expressions); - Expressions.ForEach(expr => expr.Parent = this); + _expressions = new List(expressions); + _expressions.ForEach(expr => expr.Parent = this); } - public override IEnumerator GetEnumerator() => - Expressions.GetEnumerator(); - protected override string NodeRepresentation() => "[]"; } \ No newline at end of file diff --git a/src/HydraScript.Lib/IR/Ast/Impl/Nodes/Expressions/ComplexLiterals/ObjectLiteral.cs b/src/HydraScript.Lib/IR/Ast/Impl/Nodes/Expressions/ComplexLiterals/ObjectLiteral.cs index 02a88dc0..4724abaf 100644 --- a/src/HydraScript.Lib/IR/Ast/Impl/Nodes/Expressions/ComplexLiterals/ObjectLiteral.cs +++ b/src/HydraScript.Lib/IR/Ast/Impl/Nodes/Expressions/ComplexLiterals/ObjectLiteral.cs @@ -3,16 +3,18 @@ namespace HydraScript.Lib.IR.Ast.Impl.Nodes.Expressions.ComplexLiterals; [AutoVisitable] public partial class ObjectLiteral : ComplexLiteral { - public List Properties { get; } + private readonly List _properties; + + protected override IReadOnlyList Children => + _properties; + + public IReadOnlyList Properties => _properties; public ObjectLiteral(IEnumerable properties) { - Properties = new List(properties); - Properties.ForEach(prop => prop.Parent = this); + _properties = new List(properties); + _properties.ForEach(prop => prop.Parent = this); } - public override IEnumerator GetEnumerator() => - Properties.GetEnumerator(); - protected override string NodeRepresentation() => "{}"; } \ No newline at end of file diff --git a/src/HydraScript.Lib/IR/Ast/Impl/Nodes/Expressions/ComplexLiterals/Property.cs b/src/HydraScript.Lib/IR/Ast/Impl/Nodes/Expressions/ComplexLiterals/Property.cs index adbf2691..21db416f 100644 --- a/src/HydraScript.Lib/IR/Ast/Impl/Nodes/Expressions/ComplexLiterals/Property.cs +++ b/src/HydraScript.Lib/IR/Ast/Impl/Nodes/Expressions/ComplexLiterals/Property.cs @@ -5,6 +5,9 @@ namespace HydraScript.Lib.IR.Ast.Impl.Nodes.Expressions.ComplexLiterals; [AutoVisitable] public partial class Property : Expression { + protected override IReadOnlyList Children => + [Id, Expression]; + public IdentifierReference Id { get; } public Expression Expression { get; } @@ -25,12 +28,6 @@ public void Deconstruct(out string id, out Expression expr) id = Id.Name; expr = Expression; } - - public override IEnumerator GetEnumerator() - { - yield return Id; - yield return Expression; - } protected override string NodeRepresentation() => ":"; } \ No newline at end of file diff --git a/src/HydraScript.Lib/IR/Ast/Impl/Nodes/Expressions/ConditionalExpression.cs b/src/HydraScript.Lib/IR/Ast/Impl/Nodes/Expressions/ConditionalExpression.cs index 0a0fafc6..1d32ab8b 100644 --- a/src/HydraScript.Lib/IR/Ast/Impl/Nodes/Expressions/ConditionalExpression.cs +++ b/src/HydraScript.Lib/IR/Ast/Impl/Nodes/Expressions/ConditionalExpression.cs @@ -3,6 +3,9 @@ namespace HydraScript.Lib.IR.Ast.Impl.Nodes.Expressions; [AutoVisitable] public partial class ConditionalExpression : Expression { + protected override IReadOnlyList Children => + [Test, Consequent, Alternate]; + public Expression Test { get; } public Expression Consequent { get; } public Expression Alternate { get; } @@ -18,12 +21,5 @@ public ConditionalExpression(Expression test, Expression consequent, Expression Alternate.Parent = this; } - public override IEnumerator GetEnumerator() - { - yield return Test; - yield return Consequent; - yield return Alternate; - } - protected override string NodeRepresentation() => "?:"; } \ No newline at end of file diff --git a/src/HydraScript.Lib/IR/Ast/Impl/Nodes/Expressions/MemberExpression.cs b/src/HydraScript.Lib/IR/Ast/Impl/Nodes/Expressions/MemberExpression.cs index 55206062..8aa041ef 100644 --- a/src/HydraScript.Lib/IR/Ast/Impl/Nodes/Expressions/MemberExpression.cs +++ b/src/HydraScript.Lib/IR/Ast/Impl/Nodes/Expressions/MemberExpression.cs @@ -8,24 +8,25 @@ public partial class MemberExpression : LeftHandSideExpression { private readonly IdentifierReference _identifierReference; + protected override IReadOnlyList Children => + AccessChain is not null ? [Id, AccessChain] : [Id]; + public AccessExpression? AccessChain { get; } public AccessExpression? Tail { get; } public Type ComputedIdType { get; set; } = default!; - public MemberExpression(IdentifierReference identifierReference) : - this(identifierReference, accessChain: null, tail: null) + public MemberExpression(IdentifierReference identifierReference) { + _identifierReference = identifierReference; + _identifierReference.Parent = this; } public MemberExpression( IdentifierReference identifierReference, AccessExpression? accessChain, - AccessExpression? tail) + AccessExpression? tail) : this(identifierReference) { - _identifierReference = identifierReference; - _identifierReference.Parent = this; - AccessChain = accessChain; if (AccessChain is not null) { @@ -35,20 +36,9 @@ public MemberExpression( Tail = tail; } - public override IdentifierReference Id => - _identifierReference; + public override IdentifierReference Id => _identifierReference; - public override bool Empty() => - AccessChain is null; - - public override IEnumerator GetEnumerator() - { - yield return Id; - if (AccessChain is not null) - { - yield return AccessChain; - } - } + public override bool Empty() => AccessChain is null; protected override string NodeRepresentation() => nameof(MemberExpression); } \ No newline at end of file diff --git a/src/HydraScript.Lib/IR/Ast/Impl/Nodes/Expressions/PrimaryExpressions/PrimaryExpression.cs b/src/HydraScript.Lib/IR/Ast/Impl/Nodes/Expressions/PrimaryExpressions/PrimaryExpression.cs index 59b23fb6..58805daa 100644 --- a/src/HydraScript.Lib/IR/Ast/Impl/Nodes/Expressions/PrimaryExpressions/PrimaryExpression.cs +++ b/src/HydraScript.Lib/IR/Ast/Impl/Nodes/Expressions/PrimaryExpressions/PrimaryExpression.cs @@ -5,10 +5,5 @@ namespace HydraScript.Lib.IR.Ast.Impl.Nodes.Expressions.PrimaryExpressions; [AutoVisitable] public abstract partial class PrimaryExpression : Expression { - public override IEnumerator GetEnumerator() - { - yield break; - } - public abstract IValue ToValue(); } \ No newline at end of file diff --git a/src/HydraScript.Lib/IR/Ast/Impl/Nodes/Expressions/UnaryExpression.cs b/src/HydraScript.Lib/IR/Ast/Impl/Nodes/Expressions/UnaryExpression.cs index 553cebc6..4de499d6 100644 --- a/src/HydraScript.Lib/IR/Ast/Impl/Nodes/Expressions/UnaryExpression.cs +++ b/src/HydraScript.Lib/IR/Ast/Impl/Nodes/Expressions/UnaryExpression.cs @@ -3,6 +3,9 @@ namespace HydraScript.Lib.IR.Ast.Impl.Nodes.Expressions; [AutoVisitable] public partial class UnaryExpression : Expression { + protected override IReadOnlyList Children => + [Expression]; + public string Operator { get; } public Expression Expression { get; } @@ -14,10 +17,5 @@ public UnaryExpression(string @operator, Expression expression) Expression.Parent = this; } - public override IEnumerator GetEnumerator() - { - yield return Expression; - } - protected override string NodeRepresentation() => Operator; } \ No newline at end of file diff --git a/src/HydraScript.Lib/IR/Ast/Impl/Nodes/ScriptBody.cs b/src/HydraScript.Lib/IR/Ast/Impl/Nodes/ScriptBody.cs index d1772bcd..39f7e4a5 100644 --- a/src/HydraScript.Lib/IR/Ast/Impl/Nodes/ScriptBody.cs +++ b/src/HydraScript.Lib/IR/Ast/Impl/Nodes/ScriptBody.cs @@ -3,16 +3,19 @@ namespace HydraScript.Lib.IR.Ast.Impl.Nodes; [AutoVisitable] public partial class ScriptBody : AbstractSyntaxTreeNode { - public List StatementList { get; } + private readonly List _statementList; + + protected override IReadOnlyList Children => + _statementList; + protected override bool IsRoot => true; + + public IReadOnlyList StatementList => _statementList; public ScriptBody(IEnumerable statementList) { - StatementList = new List(statementList); - StatementList.ForEach(item => item.Parent = this); + _statementList = new List(statementList); + _statementList.ForEach(item => item.Parent = this); } - public override IEnumerator GetEnumerator() => - StatementList.GetEnumerator(); - protected override string NodeRepresentation() => "Script"; } \ No newline at end of file diff --git a/src/HydraScript.Lib/IR/Ast/Impl/Nodes/Statements/BlockStatement.cs b/src/HydraScript.Lib/IR/Ast/Impl/Nodes/Statements/BlockStatement.cs index fee3b6a5..852e69e5 100644 --- a/src/HydraScript.Lib/IR/Ast/Impl/Nodes/Statements/BlockStatement.cs +++ b/src/HydraScript.Lib/IR/Ast/Impl/Nodes/Statements/BlockStatement.cs @@ -3,16 +3,18 @@ namespace HydraScript.Lib.IR.Ast.Impl.Nodes.Statements; [AutoVisitable] public partial class BlockStatement : Statement { - public List StatementList { get; } + private readonly List _statementList; + + protected override IReadOnlyList Children => + _statementList; + + public IReadOnlyList StatementList => _statementList; public BlockStatement(IEnumerable statementList) { - StatementList = new List(statementList); - StatementList.ForEach(item => item.Parent = this); + _statementList = new List(statementList); + _statementList.ForEach(item => item.Parent = this); } - public override IEnumerator GetEnumerator() => - StatementList.GetEnumerator(); - protected override string NodeRepresentation() => "{}"; } \ No newline at end of file diff --git a/src/HydraScript.Lib/IR/Ast/Impl/Nodes/Statements/ExpressionStatement.cs b/src/HydraScript.Lib/IR/Ast/Impl/Nodes/Statements/ExpressionStatement.cs index 6fbfb516..e0f80006 100644 --- a/src/HydraScript.Lib/IR/Ast/Impl/Nodes/Statements/ExpressionStatement.cs +++ b/src/HydraScript.Lib/IR/Ast/Impl/Nodes/Statements/ExpressionStatement.cs @@ -3,17 +3,15 @@ namespace HydraScript.Lib.IR.Ast.Impl.Nodes.Statements; [AutoVisitable] public partial class ExpressionStatement : Statement { + protected override IReadOnlyList Children => + [Expression]; + public Expression Expression { get; } public ExpressionStatement(Expression expression) { Expression = expression; - expression.Parent = this; - } - - public override IEnumerator GetEnumerator() - { - yield return Expression; + Expression.Parent = this; } protected override string NodeRepresentation() => nameof(ExpressionStatement); diff --git a/src/HydraScript.Lib/IR/Ast/Impl/Nodes/Statements/IfStatement.cs b/src/HydraScript.Lib/IR/Ast/Impl/Nodes/Statements/IfStatement.cs index 3be48613..e590ff72 100644 --- a/src/HydraScript.Lib/IR/Ast/Impl/Nodes/Statements/IfStatement.cs +++ b/src/HydraScript.Lib/IR/Ast/Impl/Nodes/Statements/IfStatement.cs @@ -3,6 +3,9 @@ namespace HydraScript.Lib.IR.Ast.Impl.Nodes.Statements; [AutoVisitable] public partial class IfStatement : Statement { + protected override IReadOnlyList Children => + Else is not null ? [Test, Then, Else] : [Test, Then]; + public Expression Test { get; } public Statement Then { get; } public Statement? Else { get; } @@ -22,21 +25,13 @@ public IfStatement(Expression test, Statement then, Statement? @else = null) } } - public bool Empty() => - !Then.Any() && !HasElseBlock(); - - public bool HasElseBlock() => - Else is not null && Else.Any(); - - public override IEnumerator GetEnumerator() + public bool Empty() => this is { - yield return Test; - yield return Then; - if (Else is not null) - { - yield return Else; - } - } + Then.Count: 0, + Else: null or { Count: 0 } + }; + + public bool HasElseBlock() => Else is { Count: > 0 }; protected override string NodeRepresentation() => "if"; } \ No newline at end of file diff --git a/src/HydraScript.Lib/IR/Ast/Impl/Nodes/Statements/InsideStatementJump.cs b/src/HydraScript.Lib/IR/Ast/Impl/Nodes/Statements/InsideStatementJump.cs index 26f47e1b..3fe93305 100644 --- a/src/HydraScript.Lib/IR/Ast/Impl/Nodes/Statements/InsideStatementJump.cs +++ b/src/HydraScript.Lib/IR/Ast/Impl/Nodes/Statements/InsideStatementJump.cs @@ -8,10 +8,5 @@ public partial class InsideStatementJump(string keyword) : Statement public string Keyword { get; } = keyword; - public override IEnumerator GetEnumerator() - { - yield break; - } - protected override string NodeRepresentation() => Keyword; } \ No newline at end of file diff --git a/src/HydraScript.Lib/IR/Ast/Impl/Nodes/Statements/ReturnStatement.cs b/src/HydraScript.Lib/IR/Ast/Impl/Nodes/Statements/ReturnStatement.cs index 44d4cb14..5ecb17a9 100644 --- a/src/HydraScript.Lib/IR/Ast/Impl/Nodes/Statements/ReturnStatement.cs +++ b/src/HydraScript.Lib/IR/Ast/Impl/Nodes/Statements/ReturnStatement.cs @@ -3,6 +3,9 @@ namespace HydraScript.Lib.IR.Ast.Impl.Nodes.Statements; [AutoVisitable] public partial class ReturnStatement : Statement { + protected override IReadOnlyList Children => + Expression is not null ? [Expression] : []; + public Expression? Expression { get; } public ReturnStatement(Expression? expression = null) @@ -14,15 +17,5 @@ public ReturnStatement(Expression? expression = null) } } - public override IEnumerator GetEnumerator() - { - if (Expression is null) - { - yield break; - } - - yield return Expression; - } - protected override string NodeRepresentation() => "return"; } \ No newline at end of file diff --git a/src/HydraScript.Lib/IR/Ast/Impl/Nodes/Statements/WhileStatement.cs b/src/HydraScript.Lib/IR/Ast/Impl/Nodes/Statements/WhileStatement.cs index d9930095..3f113ff4 100644 --- a/src/HydraScript.Lib/IR/Ast/Impl/Nodes/Statements/WhileStatement.cs +++ b/src/HydraScript.Lib/IR/Ast/Impl/Nodes/Statements/WhileStatement.cs @@ -3,6 +3,9 @@ namespace HydraScript.Lib.IR.Ast.Impl.Nodes.Statements; [AutoVisitable] public partial class WhileStatement : Statement { + protected override IReadOnlyList Children => + [Condition, Statement]; + public Expression Condition { get; } public Statement Statement { get; } @@ -15,11 +18,5 @@ public WhileStatement(Expression condition, Statement statement) Statement.Parent = this; } - public override IEnumerator GetEnumerator() - { - yield return Condition; - yield return Statement; - } - protected override string NodeRepresentation() => "while"; } \ No newline at end of file diff --git a/src/HydraScript.Lib/IR/Ast/Visitors/InstructionProvider.cs b/src/HydraScript.Lib/IR/Ast/Visitors/InstructionProvider.cs index d7f9f0e5..9f1f0334 100644 --- a/src/HydraScript.Lib/IR/Ast/Visitors/InstructionProvider.cs +++ b/src/HydraScript.Lib/IR/Ast/Visitors/InstructionProvider.cs @@ -32,9 +32,10 @@ public InstructionProvider() public AddressedInstructions Visit(ScriptBody visitable) { var result = new AddressedInstructions(); - foreach (var item in visitable.StatementList) + for (var i = 0; i < visitable.Count; i++) { - result.AddRange(item.Accept(This)); + var instructions = visitable[i].Accept(This); + result.AddRange(instructions); } result.Add(new Halt()); @@ -47,8 +48,9 @@ public AddressedInstructions Visit(ScriptBody visitable) public AddressedInstructions Visit(LexicalDeclaration visitable) { var result = new AddressedInstructions(); - foreach (var assignment in visitable.Assignments) + for (var i = 0; i < visitable.Count; i++) { + var assignment = visitable[i]; result.AddRange(assignment.Accept(_expressionVisitor)); } @@ -58,8 +60,9 @@ public AddressedInstructions Visit(LexicalDeclaration visitable) public AddressedInstructions Visit(BlockStatement visitable) { var result = new AddressedInstructions(); - foreach (var item in visitable.StatementList) + for (var i = 0; i < visitable.Count; i++) { + var item = visitable[i]; result.AddRange(item.Accept(This)); if (item is ReturnStatement) break; } diff --git a/src/HydraScript.Lib/IR/CheckSemantics/Exceptions/ArrayAccessException.cs b/src/HydraScript.Lib/IR/CheckSemantics/Exceptions/ArrayAccessException.cs index 59c91062..7884cdc4 100644 --- a/src/HydraScript.Lib/IR/CheckSemantics/Exceptions/ArrayAccessException.cs +++ b/src/HydraScript.Lib/IR/CheckSemantics/Exceptions/ArrayAccessException.cs @@ -1,11 +1,8 @@ using System.Diagnostics.CodeAnalysis; -using HydraScript.Lib.FrontEnd.GetTokens.Data; namespace HydraScript.Lib.IR.CheckSemantics.Exceptions; [ExcludeFromCodeCoverage] -public class ArrayAccessException : SemanticException -{ - public ArrayAccessException(Segment segment, Type type) : - base(segment, $"Array element cannot be accessed with type {type} it must be of type number") { } -} \ No newline at end of file +public class ArrayAccessException(string segment, Type type) : SemanticException( + segment, + $"Array element cannot be accessed with type {type} it must be of type number"); \ No newline at end of file diff --git a/src/HydraScript.Lib/IR/CheckSemantics/Exceptions/AssignmentToConst.cs b/src/HydraScript.Lib/IR/CheckSemantics/Exceptions/AssignmentToConst.cs index 48d187e9..afe0b251 100644 --- a/src/HydraScript.Lib/IR/CheckSemantics/Exceptions/AssignmentToConst.cs +++ b/src/HydraScript.Lib/IR/CheckSemantics/Exceptions/AssignmentToConst.cs @@ -4,8 +4,5 @@ namespace HydraScript.Lib.IR.CheckSemantics.Exceptions; [ExcludeFromCodeCoverage] -public class AssignmentToConst : SemanticException -{ - public AssignmentToConst(IdentifierReference ident) : - base(ident.Segment,$"Cannot assign to const: {ident.Name}") { } -} \ No newline at end of file +public class AssignmentToConst(IdentifierReference ident) + : SemanticException(ident.Segment, $"Cannot assign to const: {ident.Name}"); \ No newline at end of file diff --git a/src/HydraScript.Lib/IR/CheckSemantics/Exceptions/CannotDefineType.cs b/src/HydraScript.Lib/IR/CheckSemantics/Exceptions/CannotDefineType.cs index df99c271..357b09e3 100644 --- a/src/HydraScript.Lib/IR/CheckSemantics/Exceptions/CannotDefineType.cs +++ b/src/HydraScript.Lib/IR/CheckSemantics/Exceptions/CannotDefineType.cs @@ -1,11 +1,6 @@ using System.Diagnostics.CodeAnalysis; -using HydraScript.Lib.FrontEnd.GetTokens.Data; namespace HydraScript.Lib.IR.CheckSemantics.Exceptions; [ExcludeFromCodeCoverage] -public class CannotDefineType : SemanticException -{ - public CannotDefineType(Segment segment) : - base(segment, "Cannot define type") { } -} \ No newline at end of file +public class CannotDefineType(string segment) : SemanticException(segment, "Cannot define type"); \ No newline at end of file diff --git a/src/HydraScript.Lib/IR/CheckSemantics/Exceptions/ConstWithoutInitializer.cs b/src/HydraScript.Lib/IR/CheckSemantics/Exceptions/ConstWithoutInitializer.cs index 2b0aa885..76ace72f 100644 --- a/src/HydraScript.Lib/IR/CheckSemantics/Exceptions/ConstWithoutInitializer.cs +++ b/src/HydraScript.Lib/IR/CheckSemantics/Exceptions/ConstWithoutInitializer.cs @@ -4,8 +4,5 @@ namespace HydraScript.Lib.IR.CheckSemantics.Exceptions; [ExcludeFromCodeCoverage] -public class ConstWithoutInitializer : SemanticException -{ - public ConstWithoutInitializer(IdentifierReference ident) : - base(ident.Segment, $"'const' without initializer: {ident.Name}") { } -} \ No newline at end of file +public class ConstWithoutInitializer(IdentifierReference ident) : + SemanticException(ident.Segment, $"'const' without initializer: {ident.Name}"); \ No newline at end of file diff --git a/src/HydraScript.Lib/IR/CheckSemantics/Exceptions/DeclarationAlreadyExists.cs b/src/HydraScript.Lib/IR/CheckSemantics/Exceptions/DeclarationAlreadyExists.cs index ceafadc9..6ac5ed25 100644 --- a/src/HydraScript.Lib/IR/CheckSemantics/Exceptions/DeclarationAlreadyExists.cs +++ b/src/HydraScript.Lib/IR/CheckSemantics/Exceptions/DeclarationAlreadyExists.cs @@ -4,8 +4,5 @@ namespace HydraScript.Lib.IR.CheckSemantics.Exceptions; [ExcludeFromCodeCoverage] -public class DeclarationAlreadyExists : SemanticException -{ - public DeclarationAlreadyExists(IdentifierReference ident) : - base(ident.Segment, $"Declaration already exists: {ident.Name}") { } -} \ No newline at end of file +public class DeclarationAlreadyExists(IdentifierReference ident) : + SemanticException(ident.Segment, $"Declaration already exists: {ident.Name}"); \ No newline at end of file diff --git a/src/HydraScript.Lib/IR/CheckSemantics/Exceptions/FunctionWithoutReturnStatement.cs b/src/HydraScript.Lib/IR/CheckSemantics/Exceptions/FunctionWithoutReturnStatement.cs index 26bdddf1..fcf9fb6c 100644 --- a/src/HydraScript.Lib/IR/CheckSemantics/Exceptions/FunctionWithoutReturnStatement.cs +++ b/src/HydraScript.Lib/IR/CheckSemantics/Exceptions/FunctionWithoutReturnStatement.cs @@ -1,11 +1,7 @@ using System.Diagnostics.CodeAnalysis; -using HydraScript.Lib.FrontEnd.GetTokens.Data; namespace HydraScript.Lib.IR.CheckSemantics.Exceptions; [ExcludeFromCodeCoverage] -public class FunctionWithoutReturnStatement : SemanticException -{ - public FunctionWithoutReturnStatement(Segment segment) : - base(segment, "function with non-void return type must have a return statement") { } -} \ No newline at end of file +public class FunctionWithoutReturnStatement(string segment) : + SemanticException(segment, "function with non-void return type must have a return statement"); \ No newline at end of file diff --git a/src/HydraScript.Lib/IR/CheckSemantics/Exceptions/IncompatibleTypesOfOperands.cs b/src/HydraScript.Lib/IR/CheckSemantics/Exceptions/IncompatibleTypesOfOperands.cs index 8781ac8b..eb7bfd52 100644 --- a/src/HydraScript.Lib/IR/CheckSemantics/Exceptions/IncompatibleTypesOfOperands.cs +++ b/src/HydraScript.Lib/IR/CheckSemantics/Exceptions/IncompatibleTypesOfOperands.cs @@ -1,11 +1,7 @@ using System.Diagnostics.CodeAnalysis; -using HydraScript.Lib.FrontEnd.GetTokens.Data; namespace HydraScript.Lib.IR.CheckSemantics.Exceptions; [ExcludeFromCodeCoverage] -public class IncompatibleTypesOfOperands : SemanticException -{ - public IncompatibleTypesOfOperands(Segment segment, Type left, Type right) : - base(segment, $"Incompatible types of operands: {left} and {right}") { } -} \ No newline at end of file +public class IncompatibleTypesOfOperands(string segment, Type left, Type right) : + SemanticException(segment, $"Incompatible types of operands: {left} and {right}"); \ No newline at end of file diff --git a/src/HydraScript.Lib/IR/CheckSemantics/Exceptions/NonAccessibleType.cs b/src/HydraScript.Lib/IR/CheckSemantics/Exceptions/NonAccessibleType.cs index 9b76fa14..a2edae72 100644 --- a/src/HydraScript.Lib/IR/CheckSemantics/Exceptions/NonAccessibleType.cs +++ b/src/HydraScript.Lib/IR/CheckSemantics/Exceptions/NonAccessibleType.cs @@ -3,8 +3,5 @@ namespace HydraScript.Lib.IR.CheckSemantics.Exceptions; [ExcludeFromCodeCoverage] -public class NonAccessibleType : SemanticException -{ - public NonAccessibleType(Type type) : - base($"Type '{type}' is not array-like or object-like") { } -} \ No newline at end of file +public class NonAccessibleType(Type type) : + SemanticException($"Type '{type}' is not array-like or object-like"); \ No newline at end of file diff --git a/src/HydraScript.Lib/IR/CheckSemantics/Exceptions/NotBooleanTestExpression.cs b/src/HydraScript.Lib/IR/CheckSemantics/Exceptions/NotBooleanTestExpression.cs index 66bb9b3c..f1d5040c 100644 --- a/src/HydraScript.Lib/IR/CheckSemantics/Exceptions/NotBooleanTestExpression.cs +++ b/src/HydraScript.Lib/IR/CheckSemantics/Exceptions/NotBooleanTestExpression.cs @@ -1,11 +1,7 @@ using System.Diagnostics.CodeAnalysis; -using HydraScript.Lib.FrontEnd.GetTokens.Data; namespace HydraScript.Lib.IR.CheckSemantics.Exceptions; [ExcludeFromCodeCoverage] -public class NotBooleanTestExpression : SemanticException -{ - public NotBooleanTestExpression(Segment segment, Type type) : - base(segment, $"Type of expression is {type} but expected boolean") { } -} \ No newline at end of file +public class NotBooleanTestExpression(string segment, Type type) : + SemanticException(segment, $"Type of expression is {type} but expected boolean"); \ No newline at end of file diff --git a/src/HydraScript.Lib/IR/CheckSemantics/Exceptions/ObjectAccessException.cs b/src/HydraScript.Lib/IR/CheckSemantics/Exceptions/ObjectAccessException.cs index 2fbc9028..59e8183d 100644 --- a/src/HydraScript.Lib/IR/CheckSemantics/Exceptions/ObjectAccessException.cs +++ b/src/HydraScript.Lib/IR/CheckSemantics/Exceptions/ObjectAccessException.cs @@ -1,12 +1,8 @@ using System.Diagnostics.CodeAnalysis; -using HydraScript.Lib.FrontEnd.GetTokens.Data; using HydraScript.Lib.IR.CheckSemantics.Types; namespace HydraScript.Lib.IR.CheckSemantics.Exceptions; [ExcludeFromCodeCoverage] -public class ObjectAccessException : SemanticException -{ - public ObjectAccessException(Segment segment, ObjectType objectType, string field) : - base(segment, $"Object type {objectType} has no field {field}") { } -} \ No newline at end of file +public class ObjectAccessException(string segment, ObjectType objectType, string field) : + SemanticException(segment, $"Object type {objectType} has no field {field}"); \ No newline at end of file diff --git a/src/HydraScript.Lib/IR/CheckSemantics/Exceptions/OutsideOfStatement.cs b/src/HydraScript.Lib/IR/CheckSemantics/Exceptions/OutsideOfStatement.cs index 799f8807..61ec09f8 100644 --- a/src/HydraScript.Lib/IR/CheckSemantics/Exceptions/OutsideOfStatement.cs +++ b/src/HydraScript.Lib/IR/CheckSemantics/Exceptions/OutsideOfStatement.cs @@ -1,11 +1,7 @@ using System.Diagnostics.CodeAnalysis; -using HydraScript.Lib.FrontEnd.GetTokens.Data; namespace HydraScript.Lib.IR.CheckSemantics.Exceptions; [ExcludeFromCodeCoverage] -public class OutsideOfStatement : SemanticException -{ - public OutsideOfStatement(Segment segment, string keyword, string statement) : - base(segment, $"Jump \"{keyword}\" outside of statement \"{statement}\"") { } -} \ No newline at end of file +public class OutsideOfStatement(string segment, string keyword, string statement) : + SemanticException(segment, $"Jump \"{keyword}\" outside of statement \"{statement}\""); \ No newline at end of file diff --git a/src/HydraScript.Lib/IR/CheckSemantics/Exceptions/ReturnOutsideFunction.cs b/src/HydraScript.Lib/IR/CheckSemantics/Exceptions/ReturnOutsideFunction.cs index 4fcb25b5..d2898af8 100644 --- a/src/HydraScript.Lib/IR/CheckSemantics/Exceptions/ReturnOutsideFunction.cs +++ b/src/HydraScript.Lib/IR/CheckSemantics/Exceptions/ReturnOutsideFunction.cs @@ -1,11 +1,7 @@ using System.Diagnostics.CodeAnalysis; -using HydraScript.Lib.FrontEnd.GetTokens.Data; namespace HydraScript.Lib.IR.CheckSemantics.Exceptions; [ExcludeFromCodeCoverage] -public class ReturnOutsideFunction : SemanticException -{ - public ReturnOutsideFunction(Segment segment) : - base(segment, "\"return\" outside function") { } -} \ No newline at end of file +public class ReturnOutsideFunction(string segment) : + SemanticException(segment, "\"return\" outside function"); \ No newline at end of file diff --git a/src/HydraScript.Lib/IR/CheckSemantics/Exceptions/SemanticException.cs b/src/HydraScript.Lib/IR/CheckSemantics/Exceptions/SemanticException.cs index e5c2d5e9..c2dcb1b6 100644 --- a/src/HydraScript.Lib/IR/CheckSemantics/Exceptions/SemanticException.cs +++ b/src/HydraScript.Lib/IR/CheckSemantics/Exceptions/SemanticException.cs @@ -1,17 +1,24 @@ using System.Diagnostics.CodeAnalysis; -using HydraScript.Lib.FrontEnd.GetTokens.Data; namespace HydraScript.Lib.IR.CheckSemantics.Exceptions; [Serializable, ExcludeFromCodeCoverage] public abstract class SemanticException : Exception { - protected SemanticException() { } - - protected SemanticException(string message) : base(message) { } - - protected SemanticException(string message, Exception inner) : base(message, inner) { } - - protected SemanticException(Segment segment, string message) : - base($"{segment} {message}") { } + protected SemanticException() + { + } + + protected SemanticException(string message) : base(message) + { + } + + protected SemanticException(string message, Exception inner) : base(message, inner) + { + } + + protected SemanticException(string segment, string message) : + base($"{segment} {message}") + { + } } \ No newline at end of file diff --git a/src/HydraScript.Lib/IR/CheckSemantics/Exceptions/SymbolIsNotCallable.cs b/src/HydraScript.Lib/IR/CheckSemantics/Exceptions/SymbolIsNotCallable.cs index 9dd2e9cc..f8eaede5 100644 --- a/src/HydraScript.Lib/IR/CheckSemantics/Exceptions/SymbolIsNotCallable.cs +++ b/src/HydraScript.Lib/IR/CheckSemantics/Exceptions/SymbolIsNotCallable.cs @@ -1,11 +1,7 @@ using System.Diagnostics.CodeAnalysis; -using HydraScript.Lib.FrontEnd.GetTokens.Data; namespace HydraScript.Lib.IR.CheckSemantics.Exceptions; [ExcludeFromCodeCoverage] -public class SymbolIsNotCallable : SemanticException -{ - public SymbolIsNotCallable(string symbol, Segment segment) : - base(segment, $"Symbol is not callable: {symbol}") { } -} \ No newline at end of file +public class SymbolIsNotCallable(string symbol, string segment) : + SemanticException(segment, $"Symbol is not callable: {symbol}"); \ No newline at end of file diff --git a/src/HydraScript.Lib/IR/CheckSemantics/Exceptions/UnknownIdentifierReference.cs b/src/HydraScript.Lib/IR/CheckSemantics/Exceptions/UnknownIdentifierReference.cs index 523a01ce..8476d9ad 100644 --- a/src/HydraScript.Lib/IR/CheckSemantics/Exceptions/UnknownIdentifierReference.cs +++ b/src/HydraScript.Lib/IR/CheckSemantics/Exceptions/UnknownIdentifierReference.cs @@ -4,8 +4,5 @@ namespace HydraScript.Lib.IR.CheckSemantics.Exceptions; [ExcludeFromCodeCoverage] -public class UnknownIdentifierReference : SemanticException -{ - public UnknownIdentifierReference(IdentifierReference ident) : - base(ident.Segment, $"Unknown identifier reference: {ident.Name}") { } -} \ No newline at end of file +public class UnknownIdentifierReference(IdentifierReference ident) : + SemanticException(ident.Segment, $"Unknown identifier reference: {ident.Name}"); \ No newline at end of file diff --git a/src/HydraScript.Lib/IR/CheckSemantics/Exceptions/UnsupportedOperation.cs b/src/HydraScript.Lib/IR/CheckSemantics/Exceptions/UnsupportedOperation.cs index e2fe77bc..996a1707 100644 --- a/src/HydraScript.Lib/IR/CheckSemantics/Exceptions/UnsupportedOperation.cs +++ b/src/HydraScript.Lib/IR/CheckSemantics/Exceptions/UnsupportedOperation.cs @@ -1,11 +1,7 @@ using System.Diagnostics.CodeAnalysis; -using HydraScript.Lib.FrontEnd.GetTokens.Data; namespace HydraScript.Lib.IR.CheckSemantics.Exceptions; [ExcludeFromCodeCoverage] -public class UnsupportedOperation : SemanticException -{ - public UnsupportedOperation(Segment segment, Type type, string @operator) : - base(segment, $"Type {type} does not support operation {@operator}") { } -} \ No newline at end of file +public class UnsupportedOperation(string segment, Type type, string @operator) : + SemanticException(segment, $"Type {type} does not support operation {@operator}"); \ No newline at end of file diff --git a/src/HydraScript.Lib/IR/CheckSemantics/Exceptions/WrongArrayLiteralDeclaration.cs b/src/HydraScript.Lib/IR/CheckSemantics/Exceptions/WrongArrayLiteralDeclaration.cs index f14a072b..846d8230 100644 --- a/src/HydraScript.Lib/IR/CheckSemantics/Exceptions/WrongArrayLiteralDeclaration.cs +++ b/src/HydraScript.Lib/IR/CheckSemantics/Exceptions/WrongArrayLiteralDeclaration.cs @@ -1,11 +1,9 @@ using System.Diagnostics.CodeAnalysis; -using HydraScript.Lib.FrontEnd.GetTokens.Data; namespace HydraScript.Lib.IR.CheckSemantics.Exceptions; [ExcludeFromCodeCoverage] -public class WrongArrayLiteralDeclaration : SemanticException -{ - public WrongArrayLiteralDeclaration(Segment segment, Type type) : - base(segment, $"{segment} Wrong array literal declaration: all array elements must be of type {type}") { } -} \ No newline at end of file +public class WrongArrayLiteralDeclaration(string segment, Type type) : + SemanticException( + segment, + $"Wrong array literal declaration: all array elements must be of type {type}"); \ No newline at end of file diff --git a/src/HydraScript.Lib/IR/CheckSemantics/Exceptions/WrongAssignmentTarget.cs b/src/HydraScript.Lib/IR/CheckSemantics/Exceptions/WrongAssignmentTarget.cs index 5f04a672..5cb6b460 100644 --- a/src/HydraScript.Lib/IR/CheckSemantics/Exceptions/WrongAssignmentTarget.cs +++ b/src/HydraScript.Lib/IR/CheckSemantics/Exceptions/WrongAssignmentTarget.cs @@ -4,8 +4,7 @@ namespace HydraScript.Lib.IR.CheckSemantics.Exceptions; [ExcludeFromCodeCoverage] -public class WrongAssignmentTarget : SemanticException -{ - public WrongAssignmentTarget(LeftHandSideExpression lhs) : - base(lhs.Segment, $"Assignment target must be variable, property or indexer. '{lhs.Id.Name}' is {lhs.GetType().Name}") { } -} \ No newline at end of file +public class WrongAssignmentTarget(LeftHandSideExpression lhs) : + SemanticException( + lhs.Segment, + $"Assignment target must be variable, property or indexer. '{lhs.Id.Name}' is {lhs.GetType().Name}"); \ No newline at end of file diff --git a/src/HydraScript.Lib/IR/CheckSemantics/Exceptions/WrongConditionalTypes.cs b/src/HydraScript.Lib/IR/CheckSemantics/Exceptions/WrongConditionalTypes.cs index 78e87b63..458d4323 100644 --- a/src/HydraScript.Lib/IR/CheckSemantics/Exceptions/WrongConditionalTypes.cs +++ b/src/HydraScript.Lib/IR/CheckSemantics/Exceptions/WrongConditionalTypes.cs @@ -1,11 +1,13 @@ using System.Diagnostics.CodeAnalysis; -using HydraScript.Lib.FrontEnd.GetTokens.Data; namespace HydraScript.Lib.IR.CheckSemantics.Exceptions; [ExcludeFromCodeCoverage] -public class WrongConditionalTypes : SemanticException -{ - public WrongConditionalTypes(Segment cSegment, Type cType, Segment aSegment, Type aType) : - base(cSegment + aSegment, $"Different types in conditional: {cSegment} consequent - {cType}, {aSegment} alternate {aType}") { } -} \ No newline at end of file +public class WrongConditionalTypes( + string segment, + string cSegment, + Type cType, + string aSegment, + Type aType) : SemanticException( + segment, + $"Different types in conditional: {cSegment} consequent - {cType}, {aSegment} alternate {aType}"); \ No newline at end of file diff --git a/src/HydraScript.Lib/IR/CheckSemantics/Exceptions/WrongNumberOfArguments.cs b/src/HydraScript.Lib/IR/CheckSemantics/Exceptions/WrongNumberOfArguments.cs index 0260cdc3..0da12f04 100644 --- a/src/HydraScript.Lib/IR/CheckSemantics/Exceptions/WrongNumberOfArguments.cs +++ b/src/HydraScript.Lib/IR/CheckSemantics/Exceptions/WrongNumberOfArguments.cs @@ -1,11 +1,9 @@ using System.Diagnostics.CodeAnalysis; -using HydraScript.Lib.FrontEnd.GetTokens.Data; namespace HydraScript.Lib.IR.CheckSemantics.Exceptions; [ExcludeFromCodeCoverage] -public class WrongNumberOfArguments : SemanticException -{ - public WrongNumberOfArguments(Segment segment, int expected, int actual) : - base(segment, $"Wrong number of arguments: expected {expected}, actual {actual}") { } -} \ No newline at end of file +public class WrongNumberOfArguments(string segment, int expected, int actual) : + SemanticException( + segment, + $"Wrong number of arguments: expected {expected}, actual {actual}"); \ No newline at end of file diff --git a/src/HydraScript.Lib/IR/CheckSemantics/Exceptions/WrongReturnType.cs b/src/HydraScript.Lib/IR/CheckSemantics/Exceptions/WrongReturnType.cs index 6a9feefc..68ae9d53 100644 --- a/src/HydraScript.Lib/IR/CheckSemantics/Exceptions/WrongReturnType.cs +++ b/src/HydraScript.Lib/IR/CheckSemantics/Exceptions/WrongReturnType.cs @@ -1,11 +1,9 @@ using System.Diagnostics.CodeAnalysis; -using HydraScript.Lib.FrontEnd.GetTokens.Data; namespace HydraScript.Lib.IR.CheckSemantics.Exceptions; [ExcludeFromCodeCoverage] -public class WrongReturnType : SemanticException -{ - public WrongReturnType(Segment segment, Type expected, Type actual) : - base(segment, $"Wrong return type: expected {expected}, actual {actual}") { } -} \ No newline at end of file +public class WrongReturnType(string segment, Type expected, Type actual) : + SemanticException( + segment, + $"Wrong return type: expected {expected}, actual {actual}"); \ No newline at end of file diff --git a/src/HydraScript.Lib/IR/CheckSemantics/Exceptions/WrongTypeOfArgument.cs b/src/HydraScript.Lib/IR/CheckSemantics/Exceptions/WrongTypeOfArgument.cs index 77ae4927..8dc8c19b 100644 --- a/src/HydraScript.Lib/IR/CheckSemantics/Exceptions/WrongTypeOfArgument.cs +++ b/src/HydraScript.Lib/IR/CheckSemantics/Exceptions/WrongTypeOfArgument.cs @@ -1,11 +1,9 @@ using System.Diagnostics.CodeAnalysis; -using HydraScript.Lib.FrontEnd.GetTokens.Data; namespace HydraScript.Lib.IR.CheckSemantics.Exceptions; [ExcludeFromCodeCoverage] -public class WrongTypeOfArgument : SemanticException -{ - public WrongTypeOfArgument(Segment segment, Type expected, Type actual) : - base(segment,$"Wrong type of argument: expected {expected}, actual {actual}") { } -} \ No newline at end of file +public class WrongTypeOfArgument(string segment, Type expected, Type actual) : + SemanticException( + segment, + $"Wrong type of argument: expected {expected}, actual {actual}"); \ No newline at end of file diff --git a/src/HydraScript.Lib/IR/CheckSemantics/Visitors/DeclarationVisitor.cs b/src/HydraScript.Lib/IR/CheckSemantics/Visitors/DeclarationVisitor.cs index 41ce2efc..5bf69f53 100644 --- a/src/HydraScript.Lib/IR/CheckSemantics/Visitors/DeclarationVisitor.cs +++ b/src/HydraScript.Lib/IR/CheckSemantics/Visitors/DeclarationVisitor.cs @@ -27,16 +27,17 @@ public DeclarationVisitor( public override VisitUnit Visit(AbstractSyntaxTreeNode visitable) { - foreach (var child in visitable) - child.Accept(This); + for (var i = 0; i < visitable.Count; i++) + visitable[i].Accept(This); return default; } public VisitUnit Visit(LexicalDeclaration visitable) { - foreach (var assignment in visitable.Assignments) + for (var i = 0; i < visitable.Assignments.Count; i++) { + var assignment = visitable.Assignments[i]; if (visitable.SymbolTable.ContainsSymbol(assignment.Destination.Id)) throw new DeclarationAlreadyExists(assignment.Destination.Id); @@ -60,7 +61,7 @@ public VisitUnit Visit(LexicalDeclaration visitable) public VisitUnit Visit(FunctionDeclaration visitable) { - if (visitable.Parent!.SymbolTable.ContainsSymbol(visitable.Name)) + if (visitable.Parent.SymbolTable.ContainsSymbol(visitable.Name)) throw new DeclarationAlreadyExists(visitable.Name); var parameters = visitable.Arguments.Select(x => diff --git a/src/HydraScript.Lib/IR/CheckSemantics/Visitors/SemanticChecker.cs b/src/HydraScript.Lib/IR/CheckSemantics/Visitors/SemanticChecker.cs index 0d954eda..ed6acc60 100644 --- a/src/HydraScript.Lib/IR/CheckSemantics/Visitors/SemanticChecker.cs +++ b/src/HydraScript.Lib/IR/CheckSemantics/Visitors/SemanticChecker.cs @@ -56,8 +56,8 @@ public SemanticChecker( public Type Visit(ScriptBody visitable) { - foreach (var statementListItem in visitable.StatementList) - statementListItem.Accept(This); + for (var i = 0; i < visitable.Count; i++) + visitable[i].Accept(This); foreach (var funcDecl in _functionStorage.Flush()) funcDecl.Accept(This); @@ -131,11 +131,11 @@ public Type Visit(IdentifierReference visitable) } public Type Visit(Literal visitable) => - visitable.Type.BuildType(visitable.Parent!.SymbolTable); + visitable.Type.BuildType(visitable.Parent.SymbolTable); public Type Visit(ImplicitLiteral visitable) { - var type = visitable.TypeValue.BuildType(visitable.Parent!.SymbolTable); + var type = visitable.TypeValue.BuildType(visitable.Parent.SymbolTable); visitable.ComputedDefaultValue = _calculator.GetDefaultValueForType(type); return type; } @@ -181,6 +181,7 @@ public Type Visit(ConditionalExpression visitable) return cType; throw new WrongConditionalTypes( + segment: visitable.Segment, cSegment: visitable.Consequent.Segment, cType, aSegment: visitable.Alternate.Segment, @@ -249,8 +250,9 @@ public Type Visit(LexicalDeclaration visitable) { Type undefined = "undefined"; - foreach (var assignment in visitable.Assignments) + for (var i = 0; i < visitable.Assignments.Count; i++) { + var assignment = visitable.Assignments[i]; var registeredSymbol = visitable.SymbolTable.FindSymbol( assignment.Destination.Id); var sourceType = assignment.Source.Accept(This); @@ -422,7 +424,7 @@ public Type Visit(FunctionDeclaration visitable) _functionStorage.RemoveIfPresent(symbol); visitable.Statements.Accept(This); - var returnStatements = visitable.GetReturnStatements() + var returnStatements = visitable.ReturnStatements .Select(x => new { Statement = x, @@ -460,7 +462,8 @@ public Type Visit(FunctionDeclaration visitable) public Type Visit(BlockStatement visitable) { - visitable.StatementList.ForEach(x => x.Accept(This)); + for (var i = 0; i < visitable.Count; i++) + visitable[i].Accept(This); return "undefined"; } } \ No newline at end of file diff --git a/src/HydraScript.Lib/IR/CheckSemantics/Visitors/Services/Impl/SymbolTableInitializerService.cs b/src/HydraScript.Lib/IR/CheckSemantics/Visitors/Services/Impl/SymbolTableInitializerService.cs index 86dc7c1d..8564f59a 100644 --- a/src/HydraScript.Lib/IR/CheckSemantics/Visitors/Services/Impl/SymbolTableInitializerService.cs +++ b/src/HydraScript.Lib/IR/CheckSemantics/Visitors/Services/Impl/SymbolTableInitializerService.cs @@ -5,11 +5,11 @@ namespace HydraScript.Lib.IR.CheckSemantics.Visitors.Services.Impl; internal class SymbolTableInitializerService : ISymbolTableInitializerService { public void InitThroughParent(AbstractSyntaxTreeNode node) => - node.SymbolTable = node.Parent!.SymbolTable; + node.SymbolTable = node.Parent.SymbolTable; public void InitWithNewScope(AbstractSyntaxTreeNode node) { node.SymbolTable = new(); - node.SymbolTable.AddOpenScope(node.Parent!.SymbolTable); + node.SymbolTable.AddOpenScope(node.Parent.SymbolTable); } } \ No newline at end of file diff --git a/src/HydraScript.Lib/IR/CheckSemantics/Visitors/SymbolTableInitializer.cs b/src/HydraScript.Lib/IR/CheckSemantics/Visitors/SymbolTableInitializer.cs index 8b43a888..f89deae1 100644 --- a/src/HydraScript.Lib/IR/CheckSemantics/Visitors/SymbolTableInitializer.cs +++ b/src/HydraScript.Lib/IR/CheckSemantics/Visitors/SymbolTableInitializer.cs @@ -25,15 +25,17 @@ public SymbolTableInitializer( public override VisitUnit Visit(AbstractSyntaxTreeNode visitable) { _initializerService.InitThroughParent(visitable); - foreach (var child in visitable) - child.Accept(This); + for (var i = 0; i < visitable.Count; i++) + visitable[i].Accept(This); + return default; } public VisitUnit Visit(ScriptBody visitable) { visitable.SymbolTable = _provider.GetStandardLibrary(); - visitable.StatementList.ForEach(item => item.Accept(This)); + for (var i = 0; i < visitable.Count; i++) + visitable[i].Accept(This); return default; } @@ -47,7 +49,8 @@ public VisitUnit Visit(FunctionDeclaration visitable) public VisitUnit Visit(BlockStatement visitable) { _initializerService.InitWithNewScope(visitable); - visitable.StatementList.ForEach(item => item.Accept(This)); + for (var i = 0; i < visitable.Count; i++) + visitable[i].Accept(This); return default; } } \ No newline at end of file diff --git a/src/HydraScript.Lib/IR/CheckSemantics/Visitors/TypeSystemLoader.cs b/src/HydraScript.Lib/IR/CheckSemantics/Visitors/TypeSystemLoader.cs index c47d756e..a93618e1 100644 --- a/src/HydraScript.Lib/IR/CheckSemantics/Visitors/TypeSystemLoader.cs +++ b/src/HydraScript.Lib/IR/CheckSemantics/Visitors/TypeSystemLoader.cs @@ -24,15 +24,16 @@ public TypeSystemLoader( public VisitUnit Visit(ScriptBody visitable) { - visitable.StatementList.ForEach(item => item.Accept(This)); + for (var i = 0; i < visitable.Count; i++) + visitable[i].Accept(This); _resolver.Resolve(); return default; } public override VisitUnit Visit(AbstractSyntaxTreeNode visitable) { - foreach (var child in visitable) - child.Accept(This); + for (var i = 0; i < visitable.Count; i++) + visitable[i].Accept(This); return default; } diff --git a/tests/HydraScript.Tests/Unit/IR/AstNodeTests.cs b/tests/HydraScript.Tests/Unit/IR/AstNodeTests.cs index 55367f6d..7f3341e1 100644 --- a/tests/HydraScript.Tests/Unit/IR/AstNodeTests.cs +++ b/tests/HydraScript.Tests/Unit/IR/AstNodeTests.cs @@ -13,19 +13,19 @@ public class AstNodeTests public void PrecedenceTest() { var lexicalDecl = new LexicalDeclaration(false); - var stmtItemList = new List - { - lexicalDecl - }; + List stmtItemList = [lexicalDecl]; // ReSharper disable once UnusedVariable var func = new FunctionDeclaration( name: new IdentifierReference(name: Guid.NewGuid().ToString()), new TypeIdentValue( TypeId: new IdentifierReference( name: Guid.NewGuid().ToString())), - arguments: new List(), + arguments: [], new BlockStatement(stmtItemList)); + _ = new ScriptBody([func]); + Assert.True(lexicalDecl.ChildOf()); + Assert.False(lexicalDecl.ChildOf()); } } \ No newline at end of file