From ad5ed028aaa27480ef02aae5ae624bb9e24fdb30 Mon Sep 17 00:00:00 2001 From: Stepami Date: Fri, 26 Jul 2024 23:30:43 +0300 Subject: [PATCH] =?UTF-8?q?#31=20-=20=D1=83=D0=B4=D0=B0=D0=BB=D0=B8=D0=BB?= =?UTF-8?q?=20Type=20=D0=B8=D0=B7=20TypeValue?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/HydraScript.Lib/HydraScript.Lib.csproj | 2 +- .../IR/Ast/IAbstractSyntaxTreeNode.cs | 3 +- .../IR/Ast/Impl/AbstractSyntaxTreeNode.cs | 11 +++++- .../FunctionDeclaration.cs | 20 +++++++++- .../Nodes/Declarations/TypeDeclaration.cs | 12 ++++-- .../Ast/Impl/Nodes/Declarations/TypeValue.cs | 36 ++++++----------- .../Nodes/Expressions/AssignmentExpression.cs | 9 +++++ .../Nodes/Expressions/CastAsExpression.cs | 8 ++++ .../PrimaryExpressions/AbstractLiteral.cs | 16 ++++++++ .../PrimaryExpressions/ImplicitLiteral.cs | 5 +-- .../Expressions/PrimaryExpressions/Literal.cs | 6 +-- .../IR/Ast/Impl/Nodes/ScriptBody.cs | 10 +++++ .../Impl/Nodes/Statements/BlockStatement.cs | 11 ++++++ .../Visitors/DeclarationVisitor.cs | 9 +++-- .../Visitors/SemanticChecker.cs | 8 ++-- .../ISymbolTableInitializerService.cs | 10 ----- .../Impl/SymbolTableInitializerService.cs | 15 ------- .../Services/Impl/TypeDeclarationsResolver.cs | 3 +- .../Visitors/SymbolTableInitializer.cs | 16 ++++---- .../IR/CheckSemantics/Visitors/TypeBuilder.cs | 39 +++++++++++++++++++ .../Services/CodeGen/Impl/CodeGenService.cs | 1 - .../Unit/IR/SymbolTableTests.cs | 8 ++-- 22 files changed, 170 insertions(+), 88 deletions(-) create mode 100644 src/HydraScript.Lib/IR/Ast/Impl/Nodes/Expressions/PrimaryExpressions/AbstractLiteral.cs delete mode 100644 src/HydraScript.Lib/IR/CheckSemantics/Visitors/Services/ISymbolTableInitializerService.cs delete mode 100644 src/HydraScript.Lib/IR/CheckSemantics/Visitors/Services/Impl/SymbolTableInitializerService.cs create mode 100644 src/HydraScript.Lib/IR/CheckSemantics/Visitors/TypeBuilder.cs diff --git a/src/HydraScript.Lib/HydraScript.Lib.csproj b/src/HydraScript.Lib/HydraScript.Lib.csproj index 83689500..0783a6a6 100644 --- a/src/HydraScript.Lib/HydraScript.Lib.csproj +++ b/src/HydraScript.Lib/HydraScript.Lib.csproj @@ -8,7 +8,7 @@ - + diff --git a/src/HydraScript.Lib/IR/Ast/IAbstractSyntaxTreeNode.cs b/src/HydraScript.Lib/IR/Ast/IAbstractSyntaxTreeNode.cs index e874e51a..7abd5f70 100644 --- a/src/HydraScript.Lib/IR/Ast/IAbstractSyntaxTreeNode.cs +++ b/src/HydraScript.Lib/IR/Ast/IAbstractSyntaxTreeNode.cs @@ -7,6 +7,7 @@ public interface IAbstractSyntaxTreeNode : IVisitable { public IAbstractSyntaxTreeNode Parent { get; } - public SymbolTable SymbolTable { get; set; } + public SymbolTable SymbolTable { get; } + public void InitScope(SymbolTable? scope = null); public IReadOnlyList GetAllNodes(); } \ No newline at end of file diff --git a/src/HydraScript.Lib/IR/Ast/Impl/AbstractSyntaxTreeNode.cs b/src/HydraScript.Lib/IR/Ast/Impl/AbstractSyntaxTreeNode.cs index a6c5662b..4d9c62ac 100644 --- a/src/HydraScript.Lib/IR/Ast/Impl/AbstractSyntaxTreeNode.cs +++ b/src/HydraScript.Lib/IR/Ast/Impl/AbstractSyntaxTreeNode.cs @@ -7,7 +7,16 @@ public abstract class AbstractSyntaxTreeNode : IAbstractSyntaxTreeNode { public IAbstractSyntaxTreeNode Parent { get; set; } = default!; - public SymbolTable SymbolTable { get; set; } = default!; + public SymbolTable SymbolTable { get; protected set; } = default!; + + /// Базовая стратегия - инициализация через родительский узел + /// Обязательно null + public virtual void InitScope(SymbolTable? scope = null) + { + if (scope is not null) + throw new ArgumentException("'scope' must be null"); + SymbolTable = Parent.SymbolTable; + } public string Segment { get; init; } = string.Empty; 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 3fa1fa62..e47df698 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 @@ -1,16 +1,20 @@ using HydraScript.Lib.IR.Ast.Impl.Nodes.Expressions.PrimaryExpressions; using HydraScript.Lib.IR.Ast.Impl.Nodes.Statements; +using HydraScript.Lib.IR.CheckSemantics.Variables; namespace HydraScript.Lib.IR.Ast.Impl.Nodes.Declarations.AfterTypesAreLoaded; [AutoVisitable] public partial class FunctionDeclaration : AfterTypesAreLoadedDeclaration { + private readonly List _arguments; + protected override IReadOnlyList Children => [Statements]; public IdentifierReference Name { get; } public TypeValue ReturnTypeValue { get; } - public List Arguments { get; } + public IReadOnlyList Arguments => _arguments; + public BlockStatement Statements { get; } public FunctionDeclaration( @@ -21,7 +25,7 @@ public FunctionDeclaration( { Name = name; ReturnTypeValue = returnTypeValue; - Arguments = arguments; + _arguments = arguments; Statements = blockStatement; Statements.Parent = this; @@ -32,6 +36,18 @@ public FunctionDeclaration( .ToArray(); } + /// Стратегия "блока" - углубление скоупа + /// Новый скоуп + public override void InitScope(SymbolTable? scope = null) + { + ArgumentNullException.ThrowIfNull(scope); + SymbolTable = scope; + SymbolTable.AddOpenScope(Parent.SymbolTable); + + _arguments.ForEach(x => x.TypeValue.SymbolTable = Parent.SymbolTable); + ReturnTypeValue.SymbolTable = Parent.SymbolTable; + } + public bool HasReturnStatement() => ReturnStatements.Count > 0; 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 e96c61b8..5f58fad5 100644 --- a/src/HydraScript.Lib/IR/Ast/Impl/Nodes/Declarations/TypeDeclaration.cs +++ b/src/HydraScript.Lib/IR/Ast/Impl/Nodes/Declarations/TypeDeclaration.cs @@ -1,4 +1,5 @@ using HydraScript.Lib.IR.Ast.Impl.Nodes.Expressions.PrimaryExpressions; +using HydraScript.Lib.IR.CheckSemantics.Variables; namespace HydraScript.Lib.IR.Ast.Impl.Nodes.Declarations; @@ -6,10 +7,15 @@ namespace HydraScript.Lib.IR.Ast.Impl.Nodes.Declarations; public partial class TypeDeclaration(IdentifierReference typeId, TypeValue typeValue) : Declaration { public IdentifierReference TypeId { get; } = typeId; + public TypeValue TypeValue { get; } = typeValue; - public Type BuildType() => - typeValue.BuildType(SymbolTable); + /// + public override void InitScope(SymbolTable? scope = null) + { + base.InitScope(scope); + TypeValue.SymbolTable = 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/Declarations/TypeValue.cs b/src/HydraScript.Lib/IR/Ast/Impl/Nodes/Declarations/TypeValue.cs index 9f5c69aa..0aa658b7 100644 --- a/src/HydraScript.Lib/IR/Ast/Impl/Nodes/Declarations/TypeValue.cs +++ b/src/HydraScript.Lib/IR/Ast/Impl/Nodes/Declarations/TypeValue.cs @@ -1,38 +1,29 @@ using HydraScript.Lib.IR.Ast.Impl.Nodes.Expressions.PrimaryExpressions; -using HydraScript.Lib.IR.CheckSemantics.Exceptions; -using HydraScript.Lib.IR.CheckSemantics.Types; using HydraScript.Lib.IR.CheckSemantics.Variables; -using HydraScript.Lib.IR.CheckSemantics.Variables.Symbols; namespace HydraScript.Lib.IR.Ast.Impl.Nodes.Declarations; -public abstract record TypeValue +public abstract record TypeValue : IVisitable { - public abstract Type BuildType(SymbolTable symbolTable); + public SymbolTable SymbolTable { get; set; } = default!; + public abstract TReturn Accept(IVisitor visitor); } -public record TypeIdentValue(IdentifierReference TypeId) : TypeValue +[AutoVisitable] +public partial record TypeIdentValue(IdentifierReference TypeId) : TypeValue { - public override Type BuildType(SymbolTable symbolTable) => - symbolTable.FindSymbol(TypeId)?.Type ?? - throw new UnknownIdentifierReference(TypeId); - public override string ToString() => TypeId; } -public record ArrayTypeValue(TypeValue TypeValue) : TypeValue +[AutoVisitable] +public partial record ArrayTypeValue(TypeValue TypeValue) : TypeValue { - public override Type BuildType(SymbolTable symbolTable) => - new ArrayType(TypeValue.BuildType(symbolTable)); - public override string ToString() => $"{TypeValue}[]"; } -public record NullableTypeValue(TypeValue TypeValue) : TypeValue +[AutoVisitable] +public partial record NullableTypeValue(TypeValue TypeValue) : TypeValue { - public override Type BuildType(SymbolTable symbolTable) => - new NullableType(TypeValue.BuildType(symbolTable)); - public override string ToString() => $"{TypeValue}?"; } @@ -44,15 +35,10 @@ public override string ToString() => $"{Key}: {TypeValue}"; } -public record ObjectTypeValue( +[AutoVisitable] +public partial record ObjectTypeValue( IEnumerable Properties) : TypeValue { - public override Type BuildType(SymbolTable symbolTable) => - new ObjectType( - Properties.Select(x => new PropertyType( - Id: x.Key, - x.TypeValue.BuildType(symbolTable)))); - public override string ToString() => $"{{{string.Join(';', Properties)}}}"; } \ 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 fc9484df..a534c49c 100644 --- a/src/HydraScript.Lib/IR/Ast/Impl/Nodes/Expressions/AssignmentExpression.cs +++ b/src/HydraScript.Lib/IR/Ast/Impl/Nodes/Expressions/AssignmentExpression.cs @@ -1,4 +1,5 @@ using HydraScript.Lib.IR.Ast.Impl.Nodes.Declarations; +using HydraScript.Lib.IR.CheckSemantics.Variables; namespace HydraScript.Lib.IR.Ast.Impl.Nodes.Expressions; @@ -26,5 +27,13 @@ public AssignmentExpression( DestinationType = destinationType; } + /// + public override void InitScope(SymbolTable? scope = null) + { + base.InitScope(scope); + if (DestinationType is not null) + DestinationType.SymbolTable = SymbolTable; + } + 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 8c0b19dc..b5106d3a 100644 --- a/src/HydraScript.Lib/IR/Ast/Impl/Nodes/Expressions/CastAsExpression.cs +++ b/src/HydraScript.Lib/IR/Ast/Impl/Nodes/Expressions/CastAsExpression.cs @@ -1,4 +1,5 @@ using HydraScript.Lib.IR.Ast.Impl.Nodes.Declarations; +using HydraScript.Lib.IR.CheckSemantics.Variables; namespace HydraScript.Lib.IR.Ast.Impl.Nodes.Expressions; @@ -19,5 +20,12 @@ public CastAsExpression(Expression expression, TypeValue cast) Cast = cast; } + /// + public override void InitScope(SymbolTable? scope = null) + { + base.InitScope(scope); + Cast.SymbolTable = SymbolTable; + } + protected override string NodeRepresentation() => $"as {Cast}"; } \ No newline at end of file diff --git a/src/HydraScript.Lib/IR/Ast/Impl/Nodes/Expressions/PrimaryExpressions/AbstractLiteral.cs b/src/HydraScript.Lib/IR/Ast/Impl/Nodes/Expressions/PrimaryExpressions/AbstractLiteral.cs new file mode 100644 index 00000000..617b7048 --- /dev/null +++ b/src/HydraScript.Lib/IR/Ast/Impl/Nodes/Expressions/PrimaryExpressions/AbstractLiteral.cs @@ -0,0 +1,16 @@ +using HydraScript.Lib.IR.Ast.Impl.Nodes.Declarations; +using HydraScript.Lib.IR.CheckSemantics.Variables; + +namespace HydraScript.Lib.IR.Ast.Impl.Nodes.Expressions.PrimaryExpressions; + +public abstract class AbstractLiteral(TypeValue type) : PrimaryExpression +{ + public TypeValue Type { get; } = type; + + /// + public override void InitScope(SymbolTable? scope = null) + { + base.InitScope(scope); + Type.SymbolTable = Parent.SymbolTable; + } +} \ No newline at end of file diff --git a/src/HydraScript.Lib/IR/Ast/Impl/Nodes/Expressions/PrimaryExpressions/ImplicitLiteral.cs b/src/HydraScript.Lib/IR/Ast/Impl/Nodes/Expressions/PrimaryExpressions/ImplicitLiteral.cs index 2f6826ed..caca3143 100644 --- a/src/HydraScript.Lib/IR/Ast/Impl/Nodes/Expressions/PrimaryExpressions/ImplicitLiteral.cs +++ b/src/HydraScript.Lib/IR/Ast/Impl/Nodes/Expressions/PrimaryExpressions/ImplicitLiteral.cs @@ -3,13 +3,12 @@ namespace HydraScript.Lib.IR.Ast.Impl.Nodes.Expressions.PrimaryExpressions; [AutoVisitable] -public partial class ImplicitLiteral(TypeValue typeValue) : PrimaryExpression +public partial class ImplicitLiteral(TypeValue type) : AbstractLiteral(type) { - public TypeValue TypeValue { get; } = typeValue; public object? ComputedDefaultValue { private get; set; } protected override string NodeRepresentation() => - TypeValue.ToString(); + Type.ToString(); public override ValueDto ToValueDto() => ValueDto.ConstantDto( diff --git a/src/HydraScript.Lib/IR/Ast/Impl/Nodes/Expressions/PrimaryExpressions/Literal.cs b/src/HydraScript.Lib/IR/Ast/Impl/Nodes/Expressions/PrimaryExpressions/Literal.cs index 4e41f3c1..6162dc99 100644 --- a/src/HydraScript.Lib/IR/Ast/Impl/Nodes/Expressions/PrimaryExpressions/Literal.cs +++ b/src/HydraScript.Lib/IR/Ast/Impl/Nodes/Expressions/PrimaryExpressions/Literal.cs @@ -3,9 +3,8 @@ namespace HydraScript.Lib.IR.Ast.Impl.Nodes.Expressions.PrimaryExpressions; [AutoVisitable] -public partial class Literal : PrimaryExpression +public partial class Literal : AbstractLiteral { - public TypeValue Type { get; } private readonly object? _value; private readonly string _label; @@ -13,9 +12,8 @@ public Literal( TypeValue type, object? value, string segment, - string? label = null) + string? label = null) : base(type) { - Type = type; _label = (label ?? value?.ToString())!; _value = value; Segment = segment; diff --git a/src/HydraScript.Lib/IR/Ast/Impl/Nodes/ScriptBody.cs b/src/HydraScript.Lib/IR/Ast/Impl/Nodes/ScriptBody.cs index 5cf7748d..c602f169 100644 --- a/src/HydraScript.Lib/IR/Ast/Impl/Nodes/ScriptBody.cs +++ b/src/HydraScript.Lib/IR/Ast/Impl/Nodes/ScriptBody.cs @@ -1,3 +1,5 @@ +using HydraScript.Lib.IR.CheckSemantics.Variables; + namespace HydraScript.Lib.IR.Ast.Impl.Nodes; [AutoVisitable] @@ -16,5 +18,13 @@ public ScriptBody(IEnumerable statementList) _statementList.ForEach(item => item.Parent = this); } + /// В корень дерева загружается стандартная библиотека + /// Скоуп std + public override void InitScope(SymbolTable? scope = null) + { + ArgumentNullException.ThrowIfNull(scope); + SymbolTable = scope; + } + 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 54b411db..d0dabed7 100644 --- a/src/HydraScript.Lib/IR/Ast/Impl/Nodes/Statements/BlockStatement.cs +++ b/src/HydraScript.Lib/IR/Ast/Impl/Nodes/Statements/BlockStatement.cs @@ -1,3 +1,5 @@ +using HydraScript.Lib.IR.CheckSemantics.Variables; + namespace HydraScript.Lib.IR.Ast.Impl.Nodes.Statements; [AutoVisitable] @@ -16,5 +18,14 @@ public BlockStatement(IEnumerable statementList) _statementList.ForEach(item => item.Parent = this); } + /// Стратегия "блока" - углубление скоупа + /// Новый скоуп + public override void InitScope(SymbolTable? scope = null) + { + ArgumentNullException.ThrowIfNull(scope); + SymbolTable = scope; + SymbolTable.AddOpenScope(Parent.SymbolTable); + } + protected override string NodeRepresentation() => "{}"; } \ 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 bccd753b..a721ea16 100644 --- a/src/HydraScript.Lib/IR/CheckSemantics/Visitors/DeclarationVisitor.cs +++ b/src/HydraScript.Lib/IR/CheckSemantics/Visitors/DeclarationVisitor.cs @@ -16,6 +16,7 @@ public class DeclarationVisitor : VisitorNoReturnBase, { private readonly IFunctionWithUndefinedReturnStorage _functionStorage; private readonly IMethodStorage _methodStorage; + private readonly IVisitor _typeBuilder = new TypeBuilder(); public DeclarationVisitor( IFunctionWithUndefinedReturnStorage functionStorage, @@ -41,8 +42,8 @@ public VisitUnit Visit(LexicalDeclaration visitable) if (visitable.SymbolTable.ContainsSymbol(assignment.Destination.Id)) throw new DeclarationAlreadyExists(assignment.Destination.Id); - var destinationType = assignment.DestinationType?.BuildType( - assignment.SymbolTable) ?? "undefined"; + var destinationType = assignment.DestinationType?.Accept( + _typeBuilder) ?? "undefined"; if (destinationType == "undefined" && assignment.Source is ImplicitLiteral or ArrayLiteral { Expressions.Count: 0 }) @@ -68,7 +69,7 @@ public VisitUnit Visit(FunctionDeclaration visitable) { var arg = new VariableSymbol( id: x.Key, - x.TypeValue.BuildType(visitable.Parent.SymbolTable)); + x.TypeValue.Accept(_typeBuilder)); visitable.SymbolTable.AddSymbol(arg); return arg; }).ToList(); @@ -76,7 +77,7 @@ public VisitUnit Visit(FunctionDeclaration visitable) var functionSymbol = new FunctionSymbol( visitable.Name, parameters, - visitable.ReturnTypeValue.BuildType(visitable.Parent.SymbolTable), + visitable.ReturnTypeValue.Accept(_typeBuilder), isEmpty: !visitable.Statements.Any()); if (parameters is [{ Type: ObjectType objectType }, ..] && visitable.Arguments is [{ TypeValue: TypeIdentValue }, ..]) diff --git a/src/HydraScript.Lib/IR/CheckSemantics/Visitors/SemanticChecker.cs b/src/HydraScript.Lib/IR/CheckSemantics/Visitors/SemanticChecker.cs index 92675788..f83f5ac1 100644 --- a/src/HydraScript.Lib/IR/CheckSemantics/Visitors/SemanticChecker.cs +++ b/src/HydraScript.Lib/IR/CheckSemantics/Visitors/SemanticChecker.cs @@ -1,5 +1,6 @@ using HydraScript.Lib.IR.Ast; using HydraScript.Lib.IR.Ast.Impl.Nodes; +using HydraScript.Lib.IR.Ast.Impl.Nodes.Declarations; using HydraScript.Lib.IR.Ast.Impl.Nodes.Declarations.AfterTypesAreLoaded; using HydraScript.Lib.IR.Ast.Impl.Nodes.Expressions; using HydraScript.Lib.IR.Ast.Impl.Nodes.Expressions.AccessExpressions; @@ -41,6 +42,7 @@ public class SemanticChecker : VisitorBase, private readonly IDefaultValueForTypeCalculator _calculator; private readonly IFunctionWithUndefinedReturnStorage _functionStorage; private readonly IMethodStorage _methodStorage; + private readonly IVisitor _typeBuilder = new TypeBuilder(); public SemanticChecker( IDefaultValueForTypeCalculator calculator, @@ -131,11 +133,11 @@ public Type Visit(IdentifierReference visitable) } public Type Visit(Literal visitable) => - visitable.Type.BuildType(visitable.Parent.SymbolTable); + visitable.Type.Accept(_typeBuilder); public Type Visit(ImplicitLiteral visitable) { - var type = visitable.TypeValue.BuildType(visitable.Parent.SymbolTable); + var type = visitable.Type.Accept(_typeBuilder); visitable.ComputedDefaultValue = _calculator.GetDefaultValueForType(type); return type; } @@ -365,7 +367,7 @@ public Type Visit(CastAsExpression visitable) if (exprType.Equals(undefined)) throw new CannotDefineType(visitable.Expression.Segment); - return visitable.Cast.BuildType(visitable.SymbolTable) == "string" + return visitable.Cast.Accept(_typeBuilder) == "string" ? "string" : throw new NotSupportedException("Other types but 'string' have not been supported for casting yet"); } diff --git a/src/HydraScript.Lib/IR/CheckSemantics/Visitors/Services/ISymbolTableInitializerService.cs b/src/HydraScript.Lib/IR/CheckSemantics/Visitors/Services/ISymbolTableInitializerService.cs deleted file mode 100644 index 32d4c5c9..00000000 --- a/src/HydraScript.Lib/IR/CheckSemantics/Visitors/Services/ISymbolTableInitializerService.cs +++ /dev/null @@ -1,10 +0,0 @@ -using HydraScript.Lib.IR.Ast; - -namespace HydraScript.Lib.IR.CheckSemantics.Visitors.Services; - -public interface ISymbolTableInitializerService -{ - void InitThroughParent(IAbstractSyntaxTreeNode node); - - void InitWithNewScope(IAbstractSyntaxTreeNode node); -} \ 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 deleted file mode 100644 index a9e68a93..00000000 --- a/src/HydraScript.Lib/IR/CheckSemantics/Visitors/Services/Impl/SymbolTableInitializerService.cs +++ /dev/null @@ -1,15 +0,0 @@ -using HydraScript.Lib.IR.Ast; - -namespace HydraScript.Lib.IR.CheckSemantics.Visitors.Services.Impl; - -public class SymbolTableInitializerService : ISymbolTableInitializerService -{ - public void InitThroughParent(IAbstractSyntaxTreeNode node) => - node.SymbolTable = node.Parent.SymbolTable; - - public void InitWithNewScope(IAbstractSyntaxTreeNode node) - { - node.SymbolTable = new(); - node.SymbolTable.AddOpenScope(node.Parent.SymbolTable); - } -} \ No newline at end of file diff --git a/src/HydraScript.Lib/IR/CheckSemantics/Visitors/Services/Impl/TypeDeclarationsResolver.cs b/src/HydraScript.Lib/IR/CheckSemantics/Visitors/Services/Impl/TypeDeclarationsResolver.cs index 741e276c..dd204e53 100644 --- a/src/HydraScript.Lib/IR/CheckSemantics/Visitors/Services/Impl/TypeDeclarationsResolver.cs +++ b/src/HydraScript.Lib/IR/CheckSemantics/Visitors/Services/Impl/TypeDeclarationsResolver.cs @@ -7,6 +7,7 @@ public class TypeDeclarationsResolver : ITypeDeclarationsResolver { private readonly Queue _declarationsToResolve = new(); private readonly IJavaScriptTypesProvider _provider; + private readonly IVisitor _typeBuilder = new TypeBuilder(); public TypeDeclarationsResolver(IJavaScriptTypesProvider provider) => _provider = provider; @@ -24,7 +25,7 @@ public void Resolve() { declarationToResolve.SymbolTable.AddSymbol( new TypeSymbol( - declarationToResolve.BuildType(), + declarationToResolve.TypeValue.Accept(_typeBuilder), declarationToResolve.TypeId)); } diff --git a/src/HydraScript.Lib/IR/CheckSemantics/Visitors/SymbolTableInitializer.cs b/src/HydraScript.Lib/IR/CheckSemantics/Visitors/SymbolTableInitializer.cs index 991574d0..8cd5967a 100644 --- a/src/HydraScript.Lib/IR/CheckSemantics/Visitors/SymbolTableInitializer.cs +++ b/src/HydraScript.Lib/IR/CheckSemantics/Visitors/SymbolTableInitializer.cs @@ -2,6 +2,7 @@ using HydraScript.Lib.IR.Ast.Impl.Nodes; using HydraScript.Lib.IR.Ast.Impl.Nodes.Declarations.AfterTypesAreLoaded; using HydraScript.Lib.IR.Ast.Impl.Nodes.Statements; +using HydraScript.Lib.IR.CheckSemantics.Variables; using HydraScript.Lib.IR.CheckSemantics.Visitors.Services; namespace HydraScript.Lib.IR.CheckSemantics.Visitors; @@ -11,20 +12,16 @@ public class SymbolTableInitializer : VisitorNoReturnBase, IVisitor { - private readonly ISymbolTableInitializerService _initializerService; private readonly IStandardLibraryProvider _provider; - public SymbolTableInitializer( - ISymbolTableInitializerService initializerService, - IStandardLibraryProvider provider) + public SymbolTableInitializer(IStandardLibraryProvider provider) { - _initializerService = initializerService; _provider = provider; } public override VisitUnit Visit(IAbstractSyntaxTreeNode visitable) { - _initializerService.InitThroughParent(visitable); + visitable.InitScope(); for (var i = 0; i < visitable.Count; i++) visitable[i].Accept(This); @@ -33,7 +30,8 @@ public override VisitUnit Visit(IAbstractSyntaxTreeNode visitable) public VisitUnit Visit(ScriptBody visitable) { - visitable.SymbolTable = _provider.GetStandardLibrary(); + var scope = _provider.GetStandardLibrary(); + visitable.InitScope(scope); for (var i = 0; i < visitable.Count; i++) visitable[i].Accept(This); return default; @@ -41,14 +39,14 @@ public VisitUnit Visit(ScriptBody visitable) public VisitUnit Visit(FunctionDeclaration visitable) { - _initializerService.InitWithNewScope(visitable); + visitable.InitScope(scope: new SymbolTable()); visitable.Statements.Accept(This); return default; } public VisitUnit Visit(BlockStatement visitable) { - _initializerService.InitWithNewScope(visitable); + visitable.InitScope(scope: new SymbolTable()); for (var i = 0; i < visitable.Count; i++) visitable[i].Accept(This); return default; diff --git a/src/HydraScript.Lib/IR/CheckSemantics/Visitors/TypeBuilder.cs b/src/HydraScript.Lib/IR/CheckSemantics/Visitors/TypeBuilder.cs new file mode 100644 index 00000000..3752cf89 --- /dev/null +++ b/src/HydraScript.Lib/IR/CheckSemantics/Visitors/TypeBuilder.cs @@ -0,0 +1,39 @@ +using HydraScript.Lib.IR.Ast.Impl.Nodes.Declarations; +using HydraScript.Lib.IR.CheckSemantics.Exceptions; +using HydraScript.Lib.IR.CheckSemantics.Types; +using HydraScript.Lib.IR.CheckSemantics.Variables.Symbols; + +namespace HydraScript.Lib.IR.CheckSemantics.Visitors; + +public class TypeBuilder : VisitorBase, + IVisitor, + IVisitor, + IVisitor, + IVisitor +{ + public Type Visit(TypeIdentValue visitable) => + visitable.SymbolTable.FindSymbol(visitable.TypeId)?.Type ?? + throw new UnknownIdentifierReference(visitable.TypeId); + + public ArrayType Visit(ArrayTypeValue visitable) + { + visitable.TypeValue.SymbolTable = visitable.SymbolTable; + return new ArrayType(visitable.TypeValue.Accept(This)); + } + + public NullableType Visit(NullableTypeValue visitable) + { + visitable.TypeValue.SymbolTable = visitable.SymbolTable; + return new NullableType(visitable.TypeValue.Accept(This)); + } + + public ObjectType Visit(ObjectTypeValue visitable) => + new(visitable.Properties + .Select(x => + { + x.TypeValue.SymbolTable = visitable.SymbolTable; + return new PropertyType( + Id: x.Key, + x.TypeValue.Accept(This)); + })); +} \ No newline at end of file diff --git a/src/HydraScript/Services/CodeGen/Impl/CodeGenService.cs b/src/HydraScript/Services/CodeGen/Impl/CodeGenService.cs index afc19e78..ffcf4034 100644 --- a/src/HydraScript/Services/CodeGen/Impl/CodeGenService.cs +++ b/src/HydraScript/Services/CodeGen/Impl/CodeGenService.cs @@ -32,7 +32,6 @@ public CodeGenService(IFileSystem fileSystem, IOptions opti var methodStorage = new MethodStorage(); _symbolTableInitializer = new SymbolTableInitializer( - new SymbolTableInitializerService(), new StandardLibraryProvider( new JavaScriptTypesProvider())); _typeSystemLoader = new TypeSystemLoader( diff --git a/tests/HydraScript.Tests/Unit/IR/SymbolTableTests.cs b/tests/HydraScript.Tests/Unit/IR/SymbolTableTests.cs index 4f52e041..60572b68 100644 --- a/tests/HydraScript.Tests/Unit/IR/SymbolTableTests.cs +++ b/tests/HydraScript.Tests/Unit/IR/SymbolTableTests.cs @@ -37,11 +37,9 @@ public void FlatteningScopeTest() new Random().Next(10) ) ); - var script = new ScriptBody(stmtList) - { - SymbolTable = table - }; - script.ToList().ForEach(node => node.SymbolTable = table); + var script = new ScriptBody(stmtList); + script.InitScope(table); + script.ToList().ForEach(node => node.InitScope()); const string id = "ident"; var type = new Mock(id);