Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -270,7 +270,7 @@ public AddressedInstructions Visit(AssignmentExpression visitable)
public AddressedInstructions Visit(MemberExpression visitable) =>
visitable.Empty()
? []
: visitable.Tail?.Accept(This) ?? [];
: visitable.AccessChain.Last?.Value.Accept(This) ?? [];

public AddressedInstructions Visit(DotAccess visitable)
{
Expand Down Expand Up @@ -317,7 +317,7 @@ public AddressedInstructions Visit(CallExpression visitable)
if (visitable.IsEmptyCall)
return [];

var methodCall = !visitable.Empty();
var methodCall = !visitable.Member.Empty();
AddressedInstructions result = [];

if (methodCall)
Expand Down

This file was deleted.

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ public static IServiceCollection AddStaticAnalysis(this IServiceCollection servi
services.AddSingleton<IMethodStorage, MethodStorage>();
services.AddSingleton<ISymbolTableStorage, SymbolTableStorage>();

services.AddSingleton<IComputedTypesStorage, ComputedTypesStorage>();
services.AddSingleton<ITypeDeclarationsResolver, TypeDeclarationsResolver>();

services.AddSingleton<IStandardLibraryProvider, StandardLibraryProvider>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,7 @@ public VisitUnit Visit(LexicalDeclaration visitable)
if (_symbolTables[visitable.Scope].ContainsSymbol(new VariableSymbolId(assignment.Destination.Id)))
throw new DeclarationAlreadyExists(assignment.Destination.Id);

var destinationType = assignment.DestinationType?.Accept(
_typeBuilder) ?? _typesService.Undefined;
var destinationType = assignment.DestinationType?.Accept(_typeBuilder) ?? _typesService.Undefined;

if (destinationType == _typesService.Undefined &&
assignment.Source is ImplicitLiteral or ArrayLiteral { Expressions.Count: 0 })
Expand All @@ -80,7 +79,7 @@ public VisitUnit Visit(FunctionDeclaration visitable)
visitable.ReturnStatements = returnAnalyzerResult.ReturnStatements;
visitable.AllCodePathsEndedWithReturn = returnAnalyzerResult.CodePathEndedWithReturn;

var parentTable = _symbolTables[visitable.Parent.Scope];
var parentTable = _symbolTables[visitable.Parent?.Scope ?? Scope.Empty];

var parameters = new List<Type>();
for (var i = 0; i < visitable.Arguments.Count; i++)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@ internal class SemanticChecker : VisitorBase<IAbstractSyntaxTreeNode, Type>,
private readonly IFunctionWithUndefinedReturnStorage _functionStorage;
private readonly IMethodStorage _methodStorage;
private readonly ISymbolTableStorage _symbolTables;
private readonly IComputedTypesStorage _computedTypes;
private readonly IAmbiguousInvocationStorage _ambiguousInvocations;
private readonly IVisitor<TypeValue, Type> _typeBuilder;

Expand All @@ -58,15 +57,13 @@ public SemanticChecker(
IFunctionWithUndefinedReturnStorage functionStorage,
IMethodStorage methodStorage,
ISymbolTableStorage symbolTables,
IComputedTypesStorage computedTypes,
IAmbiguousInvocationStorage ambiguousInvocations,
IVisitor<TypeValue, Type> typeBuilder)
{
_typesService = typesService;
_functionStorage = functionStorage;
_methodStorage = methodStorage;
_symbolTables = symbolTables;
_computedTypes = computedTypes;
_ambiguousInvocations = ambiguousInvocations;
_typeBuilder = typeBuilder;
}
Expand All @@ -83,7 +80,6 @@ public Type Visit(ScriptBody visitable)

_methodStorage.Clear();
_symbolTables.Clear();
_computedTypes.Clear();
_ambiguousInvocations.Clear();

return _typesService.Undefined;
Expand Down Expand Up @@ -308,9 +304,6 @@ public Type Visit(AssignmentExpression visitable)
{
var typeComparer = default(CommutativeTypeEqualityComparer);

if (visitable.Destination is CallExpression)
throw new WrongAssignmentTarget(visitable.Destination);

var sourceType = visitable.Source.Accept(This);
if (!visitable.Destination.Empty())
{
Expand Down Expand Up @@ -344,17 +337,18 @@ public Type Visit(AssignmentExpression visitable)
public Type Visit(MemberExpression visitable)
{
IAbstractSyntaxTreeNode id = visitable.Id;
var idType = id.Accept(This);
visitable.ComputedIdTypeGuid = _computedTypes.Save(idType);
return visitable.Empty() ? idType : visitable.AccessChain?.Accept(This) ?? _typesService.Undefined;
return visitable.Empty()
? id.Accept(This)
: visitable.AccessChain.Last?.Value.Accept(This) ?? _typesService.Undefined;
}

public Type Visit(IndexAccess visitable)
{
var prevTypeGuid =
visitable.Prev?.ComputedTypeGuid
?? (visitable.Parent as MemberExpression)!.ComputedIdTypeGuid;
var prevType = _computedTypes.Get(prevTypeGuid);
var prevType =
visitable.Prev?.Accept(This) ??
(visitable.Parent is MemberExpression { Id: IAbstractSyntaxTreeNode id }
? id.Accept(This)
: _typesService.Undefined);

if (!prevType.TryGetOperator("[]", out var indexOperator))
throw new NonAccessibleType(prevType);
Expand All @@ -364,16 +358,16 @@ public Type Visit(IndexAccess visitable)
if (!indexOperator.TryGetResultType(indexAccessDescriptor, out var elemType))
throw new ArrayAccessException(visitable.Segment, indexType);

visitable.ComputedTypeGuid = _computedTypes.Save(elemType);
return visitable.HasNext() ? visitable.Next?.Accept(This) ?? _typesService.Undefined : elemType;
return elemType;
}

public Type Visit(DotAccess visitable)
{
var prevTypeGuid =
visitable.Prev?.ComputedTypeGuid
?? (visitable.Parent as MemberExpression)!.ComputedIdTypeGuid;
var prevType = _computedTypes.Get(prevTypeGuid);
var prevType =
visitable.Prev?.Accept(This) ??
(visitable.Parent is MemberExpression { Id: IAbstractSyntaxTreeNode id }
? id.Accept(This)
: _typesService.Undefined);

if (prevType is not ObjectType objectType)
throw new NonAccessibleType(prevType);
Expand All @@ -384,8 +378,8 @@ public Type Visit(DotAccess visitable)
return hasMethod
? objectType
: throw new ObjectAccessException(visitable.Segment, objectType, visitable.Property);
visitable.ComputedTypeGuid = _computedTypes.Save(fieldType);
return visitable.HasNext() ? visitable.Next?.Accept(This) ?? _typesService.Undefined : fieldType;

return fieldType;
}

public ObjectType Visit(WithExpression visitable)
Expand Down
24 changes: 17 additions & 7 deletions src/Domain/HydraScript.Domain.Constants/TokenTypes.cs
Original file line number Diff line number Diff line change
Expand Up @@ -71,11 +71,26 @@ public static IEnumerable<Dto> Stream
Tag: "Input",
Pattern: "[<]{3}",
Priority: 13);

yield return new(
Tag: "Assign",
Pattern: "[+]{1,2}[=]|[-][=]|[*][=]|[/][=]|[%][=]|[|][|][=]|[&][&][=]",
Priority: 14);

yield return new(
Tag: "Operator",
Pattern: "[+]{1,2}|[-]|[*]|[/]|[%]|([!]|[=])[=]|([<]|[>])[=]?|[!]|[|]{2}|[&]{2}|[~]|[:]{2}|[$]",
Priority: 14);
Pattern: "[=][=]|[!][=]|[<][=]|[>][=]",
Priority: 15);

yield return new(
Tag: "Assign",
Pattern: "[=]",
Priority: 16);

yield return new(
Tag: "Operator",
Pattern: "[+][+]|[-]|[+*/%<>!~$]|[|][|]|[&][&]|[:][:]",
Priority: 17);

yield return new(
Tag: "Comma",
Expand Down Expand Up @@ -117,11 +132,6 @@ public static IEnumerable<Dto> Stream
Pattern: "[]]",
Priority: 109);

yield return new(
Tag: "Assign",
Pattern: "[=]",
Priority: 99);

yield return new(
Tag: "QuestionMark",
Pattern: "[?]",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ namespace HydraScript.Domain.FrontEnd.Lexer.Impl;

public class TextCoordinateSystemComputer : ITextCoordinateSystemComputer
{
private readonly SearchValues<char> _sv = SearchValues.Create(['\n']);
private readonly SearchValues<char> _sv = SearchValues.Create('\n');

/// <inheritdoc/>
public IReadOnlyList<int> GetLines(string text)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ public FrozenDictionary<string, TokenType> GetTokenTypes() =>
.Select(x => x.CanIgnore
? new IgnorableType(x.Tag)
: new TokenType(x.Tag))
.Distinct()
.Concat([new EndOfProgramType(), new ErrorType()])
.ToFrozenDictionary(x => x.Tag);
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ public interface IAbstractSyntaxTreeNode :
IReadOnlyList<IAbstractSyntaxTreeNode>,
IVisitable<IAbstractSyntaxTreeNode>
{
public IAbstractSyntaxTreeNode Parent { get; }
public IAbstractSyntaxTreeNode? Parent { get; }
public Scope Scope { get; }
public void InitScope(Scope? scope = null);
public IReadOnlyList<IAbstractSyntaxTreeNode> GetAllNodes();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,17 @@ namespace HydraScript.Domain.FrontEnd.Parser.Impl.Ast;

public abstract class AbstractSyntaxTreeNode : IAbstractSyntaxTreeNode
{
public IAbstractSyntaxTreeNode Parent { get; set; } = null!;
public IAbstractSyntaxTreeNode? Parent { get; internal set; }

public Scope Scope { get; protected set; } = null!;
public Scope Scope { get; protected set; } = Scope.Empty;

/// <summary>Базовая стратегия - инициализация через родительский узел</summary>
/// <param name="scope">Обязательно <c>null</c></param>
public virtual void InitScope(Scope? scope = null)
{
if (scope is not null)
throw new ArgumentException("'scope' must be null");
Scope = Parent.Scope;
Scope = Parent?.Scope ?? Scope.Empty;
}

public string Segment { get; init; } = string.Empty;
Expand Down Expand Up @@ -45,13 +45,11 @@ public IReadOnlyList<IAbstractSyntaxTreeNode> GetAllNodes() =>
public bool ChildOf<T>(Predicate<T>? condition = null) where T : IAbstractSyntaxTreeNode
{
var parent = Parent;
while (parent != default!)
while (parent != null)
{
if (parent is T node)
{
return condition is not null
? condition(node)
: true;
return condition?.Invoke(node) ?? true;
}

parent = parent.Parent;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,10 @@ public override void InitScope(Scope? scope = null)
{
ArgumentNullException.ThrowIfNull(scope);
Scope = scope;
Scope.AddOpenScope(Parent.Scope);
Scope.AddOpenScope(Parent?.Scope ?? Scope.Empty);

_arguments.ForEach(x => x.TypeValue.Scope = Parent.Scope);
ReturnTypeValue.Scope = Parent.Scope;
_arguments.ForEach(x => x.TypeValue.Scope = Parent?.Scope ?? Scope.Empty);
ReturnTypeValue.Scope = Parent?.Scope ?? Scope.Empty;
}

protected override string NodeRepresentation() =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ public abstract record TypeValue : IVisitable<TypeValue>
{
public Scope Scope { get; set; } = null!;
public abstract TReturn Accept<TReturn>(IVisitor<TypeValue, TReturn> visitor);
public abstract TypeValue DeepClone();
}

[AutoVisitable<TypeValue>]
Expand All @@ -18,18 +19,24 @@ public partial record TypeIdentValue(IdentifierReference TypeId) : TypeValue
public static TypeIdentValue Undefined => new(new IdentifierReference("undefined"));

public override string ToString() => TypeId;

public override TypeValue DeepClone() => new TypeIdentValue(TypeId.Clone());
}

[AutoVisitable<TypeValue>]
public partial record ArrayTypeValue(TypeValue TypeValue) : TypeValue
{
public override string ToString() => $"{TypeValue}[]";

public override TypeValue DeepClone() => new ArrayTypeValue(TypeValue.DeepClone());
}

[AutoVisitable<TypeValue>]
public partial record NullableTypeValue(TypeValue TypeValue) : TypeValue
{
public override string ToString() => $"{TypeValue}?";

public override TypeValue DeepClone() => new NullableTypeValue(TypeValue.DeepClone());
}

public record PropertyTypeValue(
Expand All @@ -38,10 +45,20 @@ public record PropertyTypeValue(
{
public override string ToString() =>
$"{Key}: {TypeValue}";

public PropertyTypeValue DeepClone() => this with
{
TypeValue = TypeValue.DeepClone()
};
}

[AutoVisitable<TypeValue>]
public partial record ObjectTypeValue(List<PropertyTypeValue> Properties) : TypeValue
{
public override string ToString() => $"{{{string.Join(';', Properties)}}}";

public override TypeValue DeepClone() => new ObjectTypeValue(
Properties
.Select(p => p.DeepClone())
.ToList());
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,9 @@ namespace HydraScript.Domain.FrontEnd.Parser.Impl.Ast.Nodes.Expressions.AccessEx

public abstract class AccessExpression : Expression
{
public AccessExpression? Next { get; private set; }
protected AccessExpression? Next { get; private set; }

public AccessExpression? Prev =>
Parent as AccessExpression;

public Guid ComputedTypeGuid { get; set; } = Guid.Empty;
public AccessExpression? Prev => Parent as AccessExpression;

protected AccessExpression(AccessExpression? prev)
{
Expand All @@ -18,12 +15,10 @@ protected AccessExpression(AccessExpression? prev)
}
}

public bool HasNext() =>
Next is not null;

public bool HasPrev() =>
Prev is not null;
public bool HasPrev() => Prev is not null;

public abstract override TReturn Accept<TReturn>(
IVisitor<IAbstractSyntaxTreeNode, TReturn> visitor);

public abstract override AccessExpression Clone();
}
Loading
Loading