Skip to content

Commit

Permalink
#31 - удалил Type из TypeValue
Browse files Browse the repository at this point in the history
  • Loading branch information
Stepami committed Jul 26, 2024
1 parent bbf9d74 commit ad5ed02
Show file tree
Hide file tree
Showing 22 changed files with 170 additions and 88 deletions.
2 changes: 1 addition & 1 deletion src/HydraScript.Lib/HydraScript.Lib.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Visitor.NET" Version="4.1.1" />
<PackageReference Include="Visitor.NET" Version="4.1.2" />
<PackageReference Include="Visitor.NET.AutoVisitableGen" Version="1.3.0" />
</ItemGroup>

Expand Down
3 changes: 2 additions & 1 deletion src/HydraScript.Lib/IR/Ast/IAbstractSyntaxTreeNode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ public interface IAbstractSyntaxTreeNode :
IVisitable<IAbstractSyntaxTreeNode>
{
public IAbstractSyntaxTreeNode Parent { get; }
public SymbolTable SymbolTable { get; set; }
public SymbolTable SymbolTable { get; }
public void InitScope(SymbolTable? scope = null);
public IReadOnlyList<IAbstractSyntaxTreeNode> GetAllNodes();
}
11 changes: 10 additions & 1 deletion src/HydraScript.Lib/IR/Ast/Impl/AbstractSyntaxTreeNode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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!;

/// <summary>Базовая стратегия - инициализация через родительский узел</summary>
/// <param name="scope">Обязательно <c>null</c></param>
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;

Expand Down
Original file line number Diff line number Diff line change
@@ -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<IAbstractSyntaxTreeNode>]
public partial class FunctionDeclaration : AfterTypesAreLoadedDeclaration
{
private readonly List<PropertyTypeValue> _arguments;

protected override IReadOnlyList<IAbstractSyntaxTreeNode> Children => [Statements];

public IdentifierReference Name { get; }
public TypeValue ReturnTypeValue { get; }
public List<PropertyTypeValue> Arguments { get; }
public IReadOnlyList<PropertyTypeValue> Arguments => _arguments;

public BlockStatement Statements { get; }

public FunctionDeclaration(
Expand All @@ -21,7 +25,7 @@ public FunctionDeclaration(
{
Name = name;
ReturnTypeValue = returnTypeValue;
Arguments = arguments;
_arguments = arguments;

Statements = blockStatement;
Statements.Parent = this;
Expand All @@ -32,6 +36,18 @@ public FunctionDeclaration(
.ToArray();
}

/// <summary>Стратегия "блока" - углубление скоупа</summary>
/// <param name="scope">Новый скоуп</param>
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;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,21 @@
using HydraScript.Lib.IR.Ast.Impl.Nodes.Expressions.PrimaryExpressions;
using HydraScript.Lib.IR.CheckSemantics.Variables;

namespace HydraScript.Lib.IR.Ast.Impl.Nodes.Declarations;

[AutoVisitable<IAbstractSyntaxTreeNode>]
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);
/// <inheritdoc cref="AbstractSyntaxTreeNode.InitScope"/>
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}";
}
36 changes: 11 additions & 25 deletions src/HydraScript.Lib/IR/Ast/Impl/Nodes/Declarations/TypeValue.cs
Original file line number Diff line number Diff line change
@@ -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<TypeValue>
{
public abstract Type BuildType(SymbolTable symbolTable);
public SymbolTable SymbolTable { get; set; } = default!;
public abstract TReturn Accept<TReturn>(IVisitor<TypeValue, TReturn> visitor);
}

public record TypeIdentValue(IdentifierReference TypeId) : TypeValue
[AutoVisitable<TypeValue>]
public partial record TypeIdentValue(IdentifierReference TypeId) : TypeValue
{
public override Type BuildType(SymbolTable symbolTable) =>
symbolTable.FindSymbol<TypeSymbol>(TypeId)?.Type ??
throw new UnknownIdentifierReference(TypeId);

public override string ToString() => TypeId;
}

public record ArrayTypeValue(TypeValue TypeValue) : TypeValue
[AutoVisitable<TypeValue>]
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<TypeValue>]
public partial record NullableTypeValue(TypeValue TypeValue) : TypeValue
{
public override Type BuildType(SymbolTable symbolTable) =>
new NullableType(TypeValue.BuildType(symbolTable));

public override string ToString() => $"{TypeValue}?";
}

Expand All @@ -44,15 +35,10 @@ public override string ToString() =>
$"{Key}: {TypeValue}";
}

public record ObjectTypeValue(
[AutoVisitable<TypeValue>]
public partial record ObjectTypeValue(
IEnumerable<PropertyTypeValue> 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)}}}";
}
Original file line number Diff line number Diff line change
@@ -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;

Expand Down Expand Up @@ -26,5 +27,13 @@ public AssignmentExpression(
DestinationType = destinationType;
}

/// <inheritdoc cref="AbstractSyntaxTreeNode.InitScope"/>
public override void InitScope(SymbolTable? scope = null)
{
base.InitScope(scope);
if (DestinationType is not null)
DestinationType.SymbolTable = SymbolTable;
}

protected override string NodeRepresentation() => "=";
}
Original file line number Diff line number Diff line change
@@ -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;

Expand All @@ -19,5 +20,12 @@ public CastAsExpression(Expression expression, TypeValue cast)
Cast = cast;
}

/// <inheritdoc cref="AbstractSyntaxTreeNode.InitScope"/>
public override void InitScope(SymbolTable? scope = null)
{
base.InitScope(scope);
Cast.SymbolTable = SymbolTable;
}

protected override string NodeRepresentation() => $"as {Cast}";
}
Original file line number Diff line number Diff line change
@@ -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;

/// <inheritdoc cref="AbstractSyntaxTreeNode.InitScope"/>
public override void InitScope(SymbolTable? scope = null)
{
base.InitScope(scope);
Type.SymbolTable = Parent.SymbolTable;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,12 @@
namespace HydraScript.Lib.IR.Ast.Impl.Nodes.Expressions.PrimaryExpressions;

[AutoVisitable<IAbstractSyntaxTreeNode>]
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(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,17 @@
namespace HydraScript.Lib.IR.Ast.Impl.Nodes.Expressions.PrimaryExpressions;

[AutoVisitable<IAbstractSyntaxTreeNode>]
public partial class Literal : PrimaryExpression
public partial class Literal : AbstractLiteral
{
public TypeValue Type { get; }
private readonly object? _value;
private readonly string _label;

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;
Expand Down
10 changes: 10 additions & 0 deletions src/HydraScript.Lib/IR/Ast/Impl/Nodes/ScriptBody.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
using HydraScript.Lib.IR.CheckSemantics.Variables;

namespace HydraScript.Lib.IR.Ast.Impl.Nodes;

[AutoVisitable<IAbstractSyntaxTreeNode>]
Expand All @@ -16,5 +18,13 @@ public ScriptBody(IEnumerable<StatementListItem> statementList)
_statementList.ForEach(item => item.Parent = this);
}

/// <summary>В корень дерева загружается стандартная библиотека</summary>
/// <param name="scope">Скоуп std</param>
public override void InitScope(SymbolTable? scope = null)
{
ArgumentNullException.ThrowIfNull(scope);
SymbolTable = scope;
}

protected override string NodeRepresentation() => "Script";
}
11 changes: 11 additions & 0 deletions src/HydraScript.Lib/IR/Ast/Impl/Nodes/Statements/BlockStatement.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
using HydraScript.Lib.IR.CheckSemantics.Variables;

namespace HydraScript.Lib.IR.Ast.Impl.Nodes.Statements;

[AutoVisitable<IAbstractSyntaxTreeNode>]
Expand All @@ -16,5 +18,14 @@ public BlockStatement(IEnumerable<StatementListItem> statementList)
_statementList.ForEach(item => item.Parent = this);
}

/// <summary>Стратегия "блока" - углубление скоупа</summary>
/// <param name="scope">Новый скоуп</param>
public override void InitScope(SymbolTable? scope = null)
{
ArgumentNullException.ThrowIfNull(scope);
SymbolTable = scope;
SymbolTable.AddOpenScope(Parent.SymbolTable);
}

protected override string NodeRepresentation() => "{}";
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ public class DeclarationVisitor : VisitorNoReturnBase<IAbstractSyntaxTreeNode>,
{
private readonly IFunctionWithUndefinedReturnStorage _functionStorage;
private readonly IMethodStorage _methodStorage;
private readonly IVisitor<TypeValue, Type> _typeBuilder = new TypeBuilder();

public DeclarationVisitor(
IFunctionWithUndefinedReturnStorage functionStorage,
Expand All @@ -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 })
Expand All @@ -68,15 +69,15 @@ 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();

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 }, ..])
Expand Down
Original file line number Diff line number Diff line change
@@ -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;
Expand Down Expand Up @@ -41,6 +42,7 @@ public class SemanticChecker : VisitorBase<IAbstractSyntaxTreeNode, Type>,
private readonly IDefaultValueForTypeCalculator _calculator;
private readonly IFunctionWithUndefinedReturnStorage _functionStorage;
private readonly IMethodStorage _methodStorage;
private readonly IVisitor<TypeValue, Type> _typeBuilder = new TypeBuilder();

public SemanticChecker(
IDefaultValueForTypeCalculator calculator,
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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");
}
Expand Down
Loading

0 comments on commit ad5ed02

Please sign in to comment.