diff --git a/lib/ast/syntax/Aliases.cs b/lib/ast/syntax/Aliases.cs new file mode 100644 index 00000000..0503eb22 --- /dev/null +++ b/lib/ast/syntax/Aliases.cs @@ -0,0 +1,15 @@ +namespace vein.syntax; + +using Sprache; + +public partial class VeinSyntax +{ + internal virtual Parser AliasDeclaration => + from global in KeywordExpression("global").Token().Optional() + from keyword in KeywordExpression("alias").Token() + from aliasName in IdentifierExpression.Token() + from s in Parse.String("<|").Token() + from body in MethodParametersAndBody.Token().Select(x => new TypeOrMethod(null, x)) + .Or(TypeExpression.Token().Then(_ => Parse.Char(';').Token().Return(_)).Select(x => new TypeOrMethod(x, null))) + select new AliasSyntax(global.IsDefined, aliasName, body); +} diff --git a/lib/ast/syntax/Classes.cs b/lib/ast/syntax/Classes.cs index 40bc7714..23adcfd5 100644 --- a/lib/ast/syntax/Classes.cs +++ b/lib/ast/syntax/Classes.cs @@ -31,8 +31,8 @@ from type in TypeReference.Token().Positioned() /// [special] public foo: Type; /// protected internal virtual Parser PropertyDeclaration => - from heading in MemberDeclarationHeading - from typeAndName in NameAndType + from heading in MemberDeclarationHeading.Positioned() + from typeAndName in NameAndType.Positioned() from accessors in PropertyBody select new PropertyDeclarationSyntax(heading) { @@ -41,8 +41,8 @@ from accessors in PropertyBody Accessors = accessors.Accessors, }; protected internal virtual Parser PropertyDeclarationShortform => - from heading in MemberDeclarationHeading - from typeAndName in NameAndType + from heading in MemberDeclarationHeading.Positioned() + from typeAndName in NameAndType.Positioned() from op in Parse.String("|>").Token() from exp in QualifiedExpression.Positioned() from end in Parse.IgnoreCase(";").Token() @@ -73,7 +73,7 @@ from expression in Parse.Char('=').Token().Then(_ => QualifiedExpression).Positi }; /// examples: get; private set; get { return 0; } protected internal virtual Parser PropertyAccessor => - from heading in MemberDeclarationHeading + from heading in MemberDeclarationHeading.Positioned() from keyword in Parse.IgnoreCase("get").Or(Parse.IgnoreCase("set")).Token().Text() from body in Parse.Char(';').Return(default(BlockSyntax)).Or(Block).Commented(this) select new AccessorDeclarationSyntax(heading) @@ -85,19 +85,19 @@ from keyword in Parse.IgnoreCase("get").Or(Parse.IgnoreCase("set")).Token().Text /// example: { get; set; } protected internal virtual Parser PropertyBody => from openBrace in Parse.Char('{').Token() - from accessors in PropertyAccessor.Many() + from accessors in PropertyAccessor.Positioned().Many() from closeBrace in Parse.Char('}').Token() select new PropertyDeclarationSyntax(accessors); /// method or property declaration starting with the type and name protected internal virtual Parser MethodDeclaration => - from dec in MemberDeclarationHeading - from name in IdentifierExpression + from dec in MemberDeclarationHeading.Positioned() + from name in IdentifierExpression.Positioned() from member in MethodParametersAndBody.Select(c => c as MemberDeclarationSyntax) select member.WithName(name).WithProperties(dec); protected internal virtual Parser CtorDeclaration => - from dec in MemberDeclarationHeading + from dec in MemberDeclarationHeading.Positioned() from kw in KeywordExpression("new").Or( KeywordExpression("delete")) from member in CtorParametersAndBody.Select(c => c as MemberDeclarationSyntax) diff --git a/lib/ast/syntax/Directives.cs b/lib/ast/syntax/Directives.cs index 426eefc0..2b2243a8 100644 --- a/lib/ast/syntax/Directives.cs +++ b/lib/ast/syntax/Directives.cs @@ -1,27 +1,26 @@ -namespace vein.syntax -{ - using Sprache; +namespace vein.syntax; + +using Sprache; - public partial class VeinSyntax - { - internal virtual Parser DirectiveDeclarator(DirectiveType type) => - from start in Parse.Char('#') - from keyword in Parse.String(type.ToString().ToLowerInvariant()) - select type; +public partial class VeinSyntax +{ + internal virtual Parser DirectiveDeclarator(DirectiveType type) => + from start in Parse.Char('#') + from keyword in Parse.String(type.ToString().ToLowerInvariant()) + select type; - internal virtual Parser UseSyntax => - (from start in DirectiveDeclarator(DirectiveType.Use) - from str in StringLiteralExpression.Token() - select new UseSyntax - { - Value = str - }).Token().Named("use directive").Positioned(); - internal virtual Parser SpaceSyntax => - (from start in DirectiveDeclarator(DirectiveType.Space) - from str in StringLiteralExpression.Token() - select new SpaceSyntax - { - Value = str - }).Token().Named("space directive").Positioned(); - } + internal virtual Parser UseSyntax => + (from start in DirectiveDeclarator(DirectiveType.Use) + from str in StringLiteralExpression.Token() + select new UseSyntax + { + Value = str + }).Token().Named("use directive").Positioned(); + internal virtual Parser SpaceSyntax => + (from start in DirectiveDeclarator(DirectiveType.Space) + from str in StringLiteralExpression.Token() + select new SpaceSyntax + { + Value = str + }).Token().Named("space directive").Positioned(); } diff --git a/lib/ast/syntax/DocumentDeclaration.cs b/lib/ast/syntax/DocumentDeclaration.cs index 4a10c0ea..471085eb 100644 --- a/lib/ast/syntax/DocumentDeclaration.cs +++ b/lib/ast/syntax/DocumentDeclaration.cs @@ -25,13 +25,14 @@ public string Name public IEnumerable Directives { get; set; } public IEnumerable Members { get; set; } public IEnumerable Aspects { get; set; } + public IEnumerable Aliases { get; set; } public FileInfo FileEntity { get; set; } public string SourceText { get; set; } public string[] SourceLines => SourceText.Replace("\r", "").Split("\n"); - private List _includes; + private List? _includes; - public int[] _line_offsets; + public int[]? _line_offsets; public List Includes => _includes ??= Directives.OfExactType().Select(x => { diff --git a/lib/ast/syntax/ErrorDiff.cs b/lib/ast/syntax/ErrorDiff.cs index cb303a98..cdef0900 100644 --- a/lib/ast/syntax/ErrorDiff.cs +++ b/lib/ast/syntax/ErrorDiff.cs @@ -1,6 +1,7 @@ namespace vein.syntax { using System; + using System.Diagnostics; using System.Linq; using ishtar; using Spectre.Console; @@ -31,8 +32,9 @@ public static string DiffErrorFull(this Transform t, FileInfo doc) return ""; return $"\n\t[grey] {diff.EscapeMarkup().EscapeArgumentSymbols()} [/]\n\t[red] {arrow_line.EscapeMarkup().EscapeArgumentSymbols()} [/]"; } - catch + catch(Exception e) { + Trace.WriteLine(e.ToString()); return ""; // TODO analytic } } @@ -71,21 +73,41 @@ public static (string line, string arrow_line) DiffError(this Transform t, strin { return NewDiffError(t, sourceLines); } - catch { } + catch (Exception e) + { + Trace.WriteLine(e.ToString()); + } - var line = sourceLines[t.pos.Line].Length < t.len ? - t.pos.Line - 1 : - /*t.pos.Line*/throw new Exception("cannot detect line"); + (string line, string arrow_line) cast(int line) + { + var original = sourceLines[line]; + var err_line = original[(t.pos.Column - 1)..]; + var space1 = original[..(t.pos.Column - 1)]; + var space2 = (t.pos.Column - 1) + t.len > original.Length ? "" : original[((t.pos.Column - 1) + t.len)..]; - var original = sourceLines[line]; - var err_line = original[(t.pos.Column - 1)..]; - var space1 = original[..(t.pos.Column - 1)]; - var space2 = (t.pos.Column - 1) + t.len > original.Length ? "" : original[((t.pos.Column - 1) + t.len)..]; + return (original, + $"{new string(' ', space1.Length)}{new string('^', err_line.Length)}{new string(' ', space2.Length)}"); + } - return (original, - $"{new string(' ', space1.Length)}{new string('^', err_line.Length)}{new string(' ', space2.Length)}"); - } + try + { + return cast(t.pos.Line - 1); + } + catch (Exception e) + { + Trace.WriteLine(e.ToString()); + } + try + { + return cast(t.pos.Line); + } + catch (Exception e) + { + Trace.WriteLine(e.ToString()); + } + throw new Exception($"Cant detect line"); + } } } diff --git a/lib/ast/syntax/VeinSyntax.cs b/lib/ast/syntax/VeinSyntax.cs index cbc1a059..17b757d1 100644 --- a/lib/ast/syntax/VeinSyntax.cs +++ b/lib/ast/syntax/VeinSyntax.cs @@ -168,14 +168,13 @@ from identifier in QualifiedIdentifier }; // native("args") protected internal virtual Parser AspectSyntax => - (from kind in Aspect + (from kind in Aspect.Positioned() from args in object_creation_expression.Optional() select new AspectSyntax(kind, args)) .Positioned() .Token() .Named("aspect"); - protected internal virtual Parser AspectsExpression => (from open in Parse.Char('[') from kinds in Parse.Ref(() => AspectSyntax).Positioned().DelimitedBy(Parse.Char(',').Token()) @@ -194,7 +193,66 @@ from trailingComments in CommentParser.AnyComment.Token().Many().End() select new DocumentDeclaration { Directives = directives, - Members = members.Select(x => x.WithTrailingComments(trailingComments)) + Members = members.Select(x => x.WithTrailingComments(trailingComments)), + //Aliases = aliases.GetOrEmpty() }; + + public virtual Parser CompilationUnitV2 => + from entities in (from members in + AnyCommentUnit + .Or(DirectivesUnit) + .Or(AliasesUnit) + .Or(AspectUnit) + .Or(ClassUnit) select members).Many() + select recast(entities.SelectMany(x => x).ToList()); + + private static DocumentDeclaration recast(List entities) => new() + { + Aspects = entities.Where(x => x.kind == UnitKind.Aspect).Select(x => x.syntax) + .OfType(), + Aliases = entities.Where(x => x.kind == UnitKind.Aliases).Select(x => x.syntax).OfType(), + Directives = entities.Where(x => x.kind == UnitKind.Directive).Select(x => x.syntax) + .OfType(), + Members = entities.Where(x => x.kind == UnitKind.Class).Select(x => x.syntax) + .OfType(), + }; + + public virtual Parser> AnyCommentUnit => + from trailingComments in CommentParser.AnyComment.Token().Many() + select trailingComments.Select(x => new CompilationUnitEntity(null, UnitKind.Comments)).ToList(); + + public virtual Parser> DirectivesUnit => + from directives in SpaceSyntax.Token().Or(UseSyntax.Token()).Many() + select directives.Select(x => new CompilationUnitEntity(x, UnitKind.Directive)) + .ToList(); + + public virtual Parser> AliasesUnit => + from aliases in AliasDeclaration.Token().Many() + select aliases.Select(x => new CompilationUnitEntity(x, UnitKind.Aliases)) + .ToList(); + + public virtual Parser> AspectUnit => + from aliases in AspectDeclaration.Token().Many() + select aliases.Select(x => new CompilationUnitEntity(x, UnitKind.Aspect)) + .ToList(); + + public virtual Parser> ClassUnit => + from aliases in ClassDeclaration.Token().Many() + select aliases.Select(x => new CompilationUnitEntity(x, UnitKind.Class)) + .ToList(); } } + +public enum UnitKind +{ + Comments, + Directive, + Aliases, + Aspect, + Class +} + +public record CompilationUnitEntity(BaseSyntax syntax, UnitKind kind) +{ + +} diff --git a/lib/ast/syntax/ast/AccessorDeclarationSyntax.cs b/lib/ast/syntax/ast/AccessorDeclarationSyntax.cs index fde91924..dc5ae164 100644 --- a/lib/ast/syntax/ast/AccessorDeclarationSyntax.cs +++ b/lib/ast/syntax/ast/AccessorDeclarationSyntax.cs @@ -1,10 +1,11 @@ namespace vein.syntax; using System.Collections.Generic; +using Sprache; -public class AccessorDeclarationSyntax : MemberDeclarationSyntax +public class AccessorDeclarationSyntax : MemberDeclarationSyntax, IPositionAware { - public AccessorDeclarationSyntax(MemberDeclarationSyntax heading = null) + public AccessorDeclarationSyntax(MemberDeclarationSyntax? heading = null) : base(heading) { } @@ -20,4 +21,10 @@ public AccessorDeclarationSyntax(MemberDeclarationSyntax heading = null) public BlockSyntax Body { get; set; } public bool IsEmpty => Body == null; + + public new AccessorDeclarationSyntax SetPos(Position startPos, int length) + { + base.SetPos(startPos, length); + return this; + } } diff --git a/lib/ast/syntax/ast/AliasSyntax.cs b/lib/ast/syntax/ast/AliasSyntax.cs new file mode 100644 index 00000000..7b16c95a --- /dev/null +++ b/lib/ast/syntax/ast/AliasSyntax.cs @@ -0,0 +1,27 @@ +namespace vein.syntax; + +using Sprache; + + +public record TypeOrMethod(TypeExpression type, MethodDeclarationSyntax method); + +public class AliasSyntax(bool isGlobal, IdentifierExpression aliasName, TypeOrMethod body) : BaseSyntax, IPositionAware +{ + public bool IsGlobal { get; } = isGlobal; + public IdentifierExpression AliasName { get; } = aliasName; + public TypeExpression? Type { get; } = body.type; + public MethodDeclarationSyntax? MethodDeclaration { get; } = body.method; + + public bool IsMethod => MethodDeclaration != null; + public bool IsType => Type != null; + + public override SyntaxType Kind => SyntaxType.Alias; + public override IEnumerable ChildNodes + => GetNodes([AliasName, Type, MethodDeclaration]); + + public AliasSyntax SetPos(Position startPos, int length) + { + base.SetPos(startPos, length); + return this; + } +} diff --git a/lib/ast/syntax/ast/AspectSyntax.cs b/lib/ast/syntax/ast/AspectSyntax.cs index d5543618..9c0b8e91 100644 --- a/lib/ast/syntax/ast/AspectSyntax.cs +++ b/lib/ast/syntax/ast/AspectSyntax.cs @@ -27,7 +27,6 @@ public AspectSyntax(IdentifierExpression kind, IOption args) public bool IsNative => Name.ExpressionString.Equals("native", StringComparison.InvariantCultureIgnoreCase); public bool IsSpecial => Name.ExpressionString.Equals("special", StringComparison.InvariantCultureIgnoreCase); public bool IsForwarded => Name.ExpressionString.Equals("forwarded", StringComparison.InvariantCultureIgnoreCase); - public bool IsAlias => Name.ExpressionString.Equals("alias", StringComparison.InvariantCultureIgnoreCase); public bool IsAspectUsage => Name.ExpressionString.Equals("aspectUsage", StringComparison.InvariantCultureIgnoreCase); public new AspectSyntax SetPos(Position startPos, int length) diff --git a/lib/ast/syntax/ast/ParameterSyntax.cs b/lib/ast/syntax/ast/ParameterSyntax.cs index e429326a..93d16b1f 100644 --- a/lib/ast/syntax/ast/ParameterSyntax.cs +++ b/lib/ast/syntax/ast/ParameterSyntax.cs @@ -1,37 +1,29 @@ -namespace vein.syntax -{ - using System.Collections.Generic; - using Sprache; - - public class ParameterSyntax : BaseSyntax, IPositionAware - { - public ParameterSyntax(IdentifierExpression type, IdentifierExpression identifier) - : this(new TypeSyntax(type), identifier) - { - } - - public ParameterSyntax(TypeSyntax type, IdentifierExpression identifier) - { - Type = type; - Identifier = identifier; - } +namespace vein.syntax; - public override SyntaxType Kind => SyntaxType.Parameter; +using System.Collections.Generic; +using Sprache; - public override IEnumerable ChildNodes => GetNodes(Type); +public class ParameterSyntax(TypeSyntax type, IdentifierExpression identifier) + : BaseSyntax, IPositionAware +{ + public ParameterSyntax(IdentifierExpression type, IdentifierExpression identifier) + : this(new TypeSyntax(type), identifier) + { + } - public List Modifiers { get; set; } = new(); + public override SyntaxType Kind => SyntaxType.Parameter; - public TypeSyntax Type { get; set; } + public override IEnumerable ChildNodes => GetNodes(Type); - public IdentifierExpression Identifier { get; set; } + public List Modifiers { get; set; } = new(); - public bool IsNeedDetectType => Type is null; + public TypeSyntax Type { get; set; } = type; - public new ParameterSyntax SetPos(Position startPos, int length) - { - base.SetPos(startPos, length); - return this; - } + public IdentifierExpression Identifier { get; set; } = identifier; + + public new ParameterSyntax SetPos(Position startPos, int length) + { + base.SetPos(startPos, length); + return this; } } diff --git a/lib/ast/syntax/ast/PropertyDeclarationSyntax.cs b/lib/ast/syntax/ast/PropertyDeclarationSyntax.cs index 9ab60b65..2d1659ff 100644 --- a/lib/ast/syntax/ast/PropertyDeclarationSyntax.cs +++ b/lib/ast/syntax/ast/PropertyDeclarationSyntax.cs @@ -3,14 +3,9 @@ namespace vein.syntax; using System.Collections.Generic; using System.Linq; -public class PropertyDeclarationSyntax : MemberDeclarationSyntax +public class PropertyDeclarationSyntax(MemberDeclarationSyntax? heading = null) : MemberDeclarationSyntax(heading) { - public PropertyDeclarationSyntax(MemberDeclarationSyntax heading = null) - : base(heading) - { - } - - public PropertyDeclarationSyntax(IEnumerable accessors, MemberDeclarationSyntax heading = null) + public PropertyDeclarationSyntax(IEnumerable accessors, MemberDeclarationSyntax? heading = null) : this(heading) => Accessors = accessors.ToList(); @@ -25,9 +20,9 @@ public PropertyDeclarationSyntax(IEnumerable accessor public List Accessors { get; set; } = new(); - public AccessorDeclarationSyntax Getter => Accessors.FirstOrDefault(a => a.IsGetter); + public AccessorDeclarationSyntax? Getter => Accessors.FirstOrDefault(a => a.IsGetter); - public AccessorDeclarationSyntax Setter => Accessors.FirstOrDefault(a => a.IsSetter); + public AccessorDeclarationSyntax? Setter => Accessors.FirstOrDefault(a => a.IsSetter); public override MemberDeclarationSyntax WithTypeAndName(ParameterSyntax typeAndName) { @@ -35,7 +30,7 @@ public override MemberDeclarationSyntax WithTypeAndName(ParameterSyntax typeAndN Identifier = typeAndName.Identifier ?? typeAndName.Type.Identifier; return this; } - public ExpressionSyntax Expression { get; set; } + public ExpressionSyntax? Expression { get; set; } public bool IsShortform() => Getter is null && Setter is null && Expression is not null; diff --git a/lib/ast/syntax/ast/UseSyntax.cs b/lib/ast/syntax/ast/UseSyntax.cs index df4829c6..34f947fc 100644 --- a/lib/ast/syntax/ast/UseSyntax.cs +++ b/lib/ast/syntax/ast/UseSyntax.cs @@ -1,15 +1,14 @@ -namespace vein.syntax +namespace vein.syntax; + +using Sprache; + +public class UseSyntax : DirectiveSyntax, IPositionAware { - using Sprache; + public override DirectiveType DirectiveKind { get; } = DirectiveType.Use; - public class UseSyntax : DirectiveSyntax, IPositionAware + public new UseSyntax SetPos(Position startPos, int length) { - public override DirectiveType DirectiveKind { get; } = DirectiveType.Use; - - public new UseSyntax SetPos(Position startPos, int length) - { - base.SetPos(startPos, length); - return this; - } + base.SetPos(startPos, length); + return this; } } diff --git a/runtime/common/reflection/VeinField.cs b/runtime/common/reflection/VeinField.cs index d039d2d1..9884bd10 100644 --- a/runtime/common/reflection/VeinField.cs +++ b/runtime/common/reflection/VeinField.cs @@ -10,6 +10,12 @@ namespace vein.runtime using reflection; using static VeinTypeCode; + public abstract record VeinAlias(QualityTypeName aliasName); + + public record VeinAliasType(QualityTypeName aliasName, VeinClass type) : VeinAlias(aliasName); + + public record VeinAliasMethod(QualityTypeName aliasName, VeinMethodSignature method) : VeinAlias(aliasName); + [DebuggerDisplay("{fullName}")] public record FieldName(string fullName) { @@ -36,20 +42,13 @@ public static FieldName Resolve(int index, VeinModule module) public override string ToString() => $"{Class}.{Name}"; } - public class VeinProperty : VeinMember, IAspectable + public class VeinProperty(VeinClass owner, FieldName fullName, FieldFlags flags, VeinClass propType) + : VeinMember, IAspectable { - public VeinProperty(VeinClass owner, FieldName fullName, FieldFlags flags, VeinClass propType) - { - this.Owner = owner; - this.FullName = fullName; - this.Flags = flags; - this.PropType = propType; - } - - public FieldName FullName { get; protected internal set; } - public VeinClass PropType { get; set; } - public FieldFlags Flags { get; set; } - public VeinClass Owner { get; set; } + public FieldName FullName { get; protected internal set; } = fullName; + public VeinClass PropType { get; set; } = propType; + public FieldFlags Flags { get; set; } = flags; + public VeinClass Owner { get; set; } = owner; public List Aspects { get; } = new(); public override string Name @@ -59,18 +58,18 @@ public override string Name } public override VeinMemberKind Kind => VeinMemberKind.Field; - public bool IsLiteral => this.Flags.HasFlag(FieldFlags.Literal); - public bool IsStatic => this.Flags.HasFlag(FieldFlags.Static); - public bool IsPublic => this.Flags.HasFlag(FieldFlags.Public); - public bool IsReadonly => this.Flags.HasFlag(FieldFlags.Readonly) && Setter is null; + public bool IsLiteral => Flags.HasFlag(FieldFlags.Literal); + public bool IsStatic => Flags.HasFlag(FieldFlags.Static); + public bool IsPublic => Flags.HasFlag(FieldFlags.Public); + public bool IsReadonly => Flags.HasFlag(FieldFlags.Readonly) && Setter is null; public bool IsPrivate => !IsPublic; [MaybeNull] public VeinMethod Getter { get; set; } [MaybeNull] public VeinMethod Setter { get; set; } [MaybeNull] public VeinField ShadowField { get; set; } - public static FieldName GetShadowFieldName(FieldName propName) - => new FieldName($"$_prop_shadow_{propName.Name}_", propName.Class); + public static FieldName GetShadowFieldName(FieldName propName) => + new($"$_prop_shadow_{propName.Name}_", propName.Class); public static FieldName GetShadowFieldName(string propName) => $"$_prop_shadow_{propName}_"; @@ -109,13 +108,13 @@ public static VeinProperty RestoreFrom(string name, VeinClass clazz) if (shadowField is null) return null; var prop = new VeinProperty(clazz, new FieldName(name, clazz.Name), shadowField.Flags, - shadowField.FieldType); - prop.ShadowField = shadowField; + shadowField.FieldType) + { + ShadowField = shadowField + }; - var setterArgs = shadowField.IsStatic ? - new VeinClass[0] : new VeinClass[1] { clazz }; - var getterArgs = shadowField.IsStatic ? - new VeinClass[1] { shadowField.FieldType } : new VeinClass[2] { clazz, shadowField.FieldType }; + var setterArgs = shadowField.IsStatic ? Array.Empty() : [clazz]; + var getterArgs = shadowField.IsStatic ? [shadowField.FieldType] : new[] { clazz, shadowField.FieldType }; var getMethod = clazz.FindMethod(GetterFnName(name), setterArgs, true); @@ -131,19 +130,13 @@ public static VeinProperty RestoreFrom(string name, VeinClass clazz) } } - public class VeinField : VeinMember, IAspectable + public class VeinField(VeinClass owner, FieldName fullName, FieldFlags flags, VeinClass fieldType) + : VeinMember, IAspectable { - public VeinField(VeinClass owner, FieldName fullName, FieldFlags flags, VeinClass fieldType) - { - this.Owner = owner; - this.FullName = fullName; - this.Flags = flags; - this.FieldType = fieldType; - } - public FieldName FullName { get; protected internal set; } - public VeinClass FieldType { get; set; } - public FieldFlags Flags { get; set; } - public VeinClass Owner { get; set; } + public FieldName FullName { get; protected internal set; } = fullName; + public VeinClass FieldType { get; set; } = fieldType; + public FieldFlags Flags { get; set; } = flags; + public VeinClass Owner { get; set; } = owner; public List Aspects { get; } = new(); public override string Name @@ -154,10 +147,10 @@ public override string Name public override VeinMemberKind Kind => VeinMemberKind.Field; - public override bool IsSpecial => this.Flags.HasFlag(FieldFlags.Special); - public bool IsLiteral => this.Flags.HasFlag(FieldFlags.Literal); - public bool IsStatic => this.Flags.HasFlag(FieldFlags.Static); - public bool IsPublic => this.Flags.HasFlag(FieldFlags.Public); + public override bool IsSpecial => Flags.HasFlag(FieldFlags.Special); + public bool IsLiteral => Flags.HasFlag(FieldFlags.Literal); + public bool IsStatic => Flags.HasFlag(FieldFlags.Static); + public bool IsPublic => Flags.HasFlag(FieldFlags.Public); public bool IsPrivate => !IsPublic; } diff --git a/runtime/common/reflection/VeinModule.cs b/runtime/common/reflection/VeinModule.cs index 53ad0e55..007f5e32 100644 --- a/runtime/common/reflection/VeinModule.cs +++ b/runtime/common/reflection/VeinModule.cs @@ -20,6 +20,7 @@ public class VeinModule protected internal List aspects { get; } = new(); protected internal ConstStorage const_table { get; set; } = new(); protected internal readonly List class_table = new(); + protected internal readonly List alias_table = new(); protected internal readonly Dictionary strings_table = new(); protected internal readonly Dictionary types_table = new(); protected internal readonly Dictionary fields_table = new(); @@ -86,7 +87,7 @@ public VeinClass FindType(string typename, List includes, bool throwWhen public VeinClass FindType(QualityTypeName type, bool findExternally = false, bool dropUnresolvedException = true) { if (!findExternally) - findExternally = this.Name != type.AssemblyName; + findExternally = Name != type.AssemblyName; var result = class_table.FirstOrDefault(filter); if (result is not null) diff --git a/runtime/ishtar.base/emit/ClassBuilder.cs b/runtime/ishtar.base/emit/ClassBuilder.cs index 28241a70..ec752a0d 100644 --- a/runtime/ishtar.base/emit/ClassBuilder.cs +++ b/runtime/ishtar.base/emit/ClassBuilder.cs @@ -110,11 +110,11 @@ public VeinProperty DefineAutoProperty(string name, FieldFlags flags, VeinClass var args = prop.IsStatic - ? new VeinArgumentRef[0] - : new VeinArgumentRef[1] - { + ? Array.Empty() + : + [ new VeinArgumentRef(VeinArgumentRef.THIS_ARGUMENT, prop.Owner) - }; + ]; var getter = DefineMethod(VeinProperty.GetterFnName(name), VeinProperty.ConvertShadowFlags(flags), propType, args); @@ -137,12 +137,12 @@ public VeinProperty DefineAutoProperty(string name, FieldFlags flags, VeinClass if (flags.HasFlag(FieldFlags.Readonly)) return prop; args = prop.IsStatic - ? new VeinArgumentRef[1] { new VeinArgumentRef("value", prop.PropType) } - : new VeinArgumentRef[2] - { + ? [new VeinArgumentRef("value", prop.PropType)] + : + [ new VeinArgumentRef(VeinArgumentRef.THIS_ARGUMENT, prop.Owner), new VeinArgumentRef("value", prop.PropType) - }; + ]; var setter = DefineMethod(VeinProperty.SetterFnName(name), VeinProperty.ConvertShadowFlags(flags), VeinTypeCode.TYPE_VOID.AsClass(propType), diff --git a/runtime/ishtar.base/emit/ILGenerator.cs b/runtime/ishtar.base/emit/ILGenerator.cs index efd3ea3d..67069b75 100644 --- a/runtime/ishtar.base/emit/ILGenerator.cs +++ b/runtime/ishtar.base/emit/ILGenerator.cs @@ -328,14 +328,14 @@ public virtual ILGenerator Emit(OpCode opcode, VeinMethod method) public ExceptionBlockInfo[] GetExceptions() { if (exceptionBlocks is null) - return new ExceptionBlockInfo[0]; - return exceptionBlocks.Where(x => x is not null).ToArray() ?? new ExceptionBlockInfo[0]; + return Array.Empty(); + return exceptionBlocks.Where(x => x is not null).ToArray() ?? Array.Empty(); } public VeinClass[] GetEffectedExceptions() { if (exceptionIndex == 0) - return new VeinClass[0]; + return Array.Empty(); return new HashSet(exceptionBlocks.Where(x => x is not null) .SelectMany(x => x.CatchClass).Where(x => x is not null)).ToArray(); } @@ -483,6 +483,8 @@ public virtual void UseLabel(Label loc) /// public int[] GetLabels() => _labels; + public byte GetStackSize() => 64; // todo calculate stack size + internal byte[] BakeByteArray() { if (_position == 0) diff --git a/runtime/ishtar.base/emit/MethodBuilder.cs b/runtime/ishtar.base/emit/MethodBuilder.cs index faeb8a67..254bde6a 100644 --- a/runtime/ishtar.base/emit/MethodBuilder.cs +++ b/runtime/ishtar.base/emit/MethodBuilder.cs @@ -1,134 +1,125 @@ -namespace ishtar.emit -{ - using System; - using System.Collections.Generic; - using System.IO; - using System.Linq; - using System.Text; - using extensions; - using vein.extensions; - using vein.runtime; - using static vein.runtime.MethodFlags; - - public class MethodBuilder : VeinMethod, IBaker - { - internal readonly ClassBuilder classBuilder; - internal VeinModuleBuilder moduleBuilder - => classBuilder?.moduleBuilder; - private readonly ILGenerator _generator; +namespace ishtar.emit; +using System; +using System.IO; +using System.Linq; +using System.Text; +using extensions; +using vein.extensions; +using vein.runtime; +using static vein.runtime.MethodFlags; - internal MethodBuilder(ClassBuilder clazz, string name, VeinClass returnType, params VeinArgumentRef[] args) - : base(name, 0, returnType, clazz, args) - { - classBuilder = clazz; - Owner = clazz; - _generator = new ILGenerator(this); - clazz.moduleBuilder.InternString(Name); - } - /// - /// Get body . - /// - public ILGenerator GetGenerator() => _generator; - /// - /// Bake byte code. - /// - public byte[] BakeByteArray() - { - var idx = classBuilder.moduleBuilder.InternString(Name); - using var mem = new MemoryStream(); - using var binary = new BinaryWriter(mem); - if (IsExtern || IsAbstract) - { - binary.Write(idx); // $method name - binary.Write((short)Flags); // $flags - binary.Write(0); // body size - binary.Write((byte)0); // stack size TODO - binary.Write((byte)0); // locals size - binary.WriteTypeName(ReturnType.FullName, moduleBuilder); - WriteArguments(binary); - binary.Write(new byte[0]); // IL Body - return mem.ToArray(); - } +public class MethodBuilder : VeinMethod, IBaker +{ + internal readonly ClassBuilder classBuilder; + internal VeinModuleBuilder moduleBuilder + => classBuilder?.moduleBuilder; + private readonly ILGenerator _generator; - var body = _generator.BakeByteArray(); + internal MethodBuilder(ClassBuilder clazz, string name, VeinClass returnType, params VeinArgumentRef[] args) + : base(name, 0, returnType, clazz, args) + { + classBuilder = clazz; + Owner = clazz; + _generator = new ILGenerator(this); + clazz.moduleBuilder.InternString(Name); + } + /// + /// Get body . + /// + public ILGenerator GetGenerator() => _generator; + /// + /// Bake byte code. + /// + public byte[] BakeByteArray() + { + var idx = classBuilder.moduleBuilder.InternString(Name); + using var mem = new MemoryStream(); + using var binary = new BinaryWriter(mem); + if (IsExtern || IsAbstract) + { binary.Write(idx); // $method name binary.Write((short)Flags); // $flags - binary.Write(body.Length); // body size - binary.Write((byte)64); // stack size TODO - binary.Write((byte)_generator.LocalsSize); // locals size + binary.Write(0); // body size + binary.Write((byte)0); // stack size + binary.Write((byte)0); // locals size binary.WriteTypeName(ReturnType.FullName, moduleBuilder); - WriteArguments(binary); - binary.Write(body); // IL Body - + binary.WriteArguments(Signature, moduleBuilder); + binary.Write(Array.Empty()); // IL Body return mem.ToArray(); } - private void WriteArguments(BinaryWriter binary) + var body = _generator.BakeByteArray(); + + binary.Write(idx); // $method name + binary.Write((short)Flags); // $flags + binary.Write(body.Length); // body size + binary.Write(_generator.GetStackSize()); + binary.Write((byte)_generator.LocalsSize); // locals size + binary.WriteTypeName(ReturnType.FullName, moduleBuilder); + binary.WriteArguments(Signature, moduleBuilder); + binary.Write(body); // IL Body + + return mem.ToArray(); + } + + /// + /// Bake debug view of byte code. + /// + public string BakeDebugString() + { + var str = new StringBuilder(); + var args = Signature.ToTemplateString(); + if (Flags.HasFlag(Extern)) { - binary.Write(ArgLength); - foreach (var argument in Arguments) - { - binary.Write(moduleBuilder.InternString(argument.Name)); - binary.WriteTypeName(argument.Type.FullName, moduleBuilder); - } + if (Signature.IsGeneric) + str.AppendLine($".method extern {RawName}[{Signature.Arguments.Where(x => x.IsGeneric).Select(x => x.TypeArg!.ToTemplateString()).Join(',')}] {args} {Flags.EnumerateFlags([None, Extern]).Join(' ').ToLowerInvariant()}"); + else + str.AppendLine($".method extern {RawName} {args} {Flags.EnumerateFlags([None, Extern]).Join(' ').ToLowerInvariant()}"); + return str.ToString(); } - /// - /// Bake debug view of byte code. - /// - public string BakeDebugString() - { - var str = new StringBuilder(); - var args = Arguments.Select(x => $"{x.Name}: {x.Type.Name}").Join(", "); - if (Flags.HasFlag(Extern)) - { - str.Append($".method extern {RawName} ({args}) {Flags.EnumerateFlags(new[] { None, Extern }).Join(' ').ToLowerInvariant()}"); - str.AppendLine($" -> {ReturnType.FullName.Name};"); - return str.ToString(); - } - var body = _generator.BakeDebugString(); - var expcetions = _generator.GetExceptions(); + var body = _generator.BakeDebugString(); - foreach (var exClass in _generator.GetEffectedExceptions()) - str.AppendLine($"@effect {exClass.FullName.NameWithNS};"); + foreach (var exClass in _generator.GetEffectedExceptions()) + str.AppendLine($"@effect {exClass.FullName.NameWithNS};"); - str.Append($".method {(IsSpecial ? "special " : "")}'{RawName}' ({args}) {Flags.EnumerateFlags(new[] { None, Extern }).Join(' ').ToLowerInvariant()}"); - str.AppendLine($" -> {ReturnType.FullName.Name}"); - if (Flags.HasFlag(Abstract)) - return str.ToString(); - str.AppendLine("{"); - str.AppendLine($"\t.size {_generator.ILOffset}"); - str.AppendLine($"\t.maxstack 0x{64:X8}"); - str.AppendLine($"\t.locals 0x{_generator.LocalsSize:X8}"); - if (!string.IsNullOrEmpty(body)) - { - str.AppendLine($"\t"); - str.AppendLine($"{body.Split("\n").Select(x => $"\t{x}").Join("\n").TrimEnd('\n')}"); - } - str.AppendLine("}"); + str.AppendLine($".method {(IsSpecial ? "special " : "")}'{RawName}' [{Signature.Arguments.Where(x => x.IsGeneric).Select(x => x.TypeArg!.ToTemplateString()).Join(',')}] {args} {Flags.EnumerateFlags([None, Extern]).Join(' ').ToLowerInvariant()}"); + if (Flags.HasFlag(Abstract)) return str.ToString(); + str.AppendLine("{"); + str.AppendLine($"\t.size {_generator.ILOffset}"); + str.AppendLine($"\t.maxstack 0x{_generator.GetStackSize():X8}"); + str.AppendLine($"\t.locals 0x{_generator.LocalsSize:X8}"); + if (!string.IsNullOrEmpty(body)) + { + str.AppendLine($"\t"); + str.AppendLine($"{body.Split("\n").Select(x => $"\t{x}").Join("\n").TrimEnd('\n')}"); } + str.AppendLine("}"); + return str.ToString(); + } - #region Arg&Locals manage (NEED REFACTORING) + #region Arg&Locals manage (NEED REFACTORING) - internal int? GetArgumentIndex(FieldName @ref) - => getArg(@ref)?.idx; + internal int? GetArgumentIndex(FieldName @ref) + => getArg(@ref)?.idx; - internal int? GetLocalIndex(FieldName @ref) - => getLocal(@ref)?.idx; - private (int idx, VeinArgumentRef arg)? getLocal(FieldName @ref) - { - var (key, value) = Locals - .FirstOrDefault(x - => x.Value.Name.Equals(@ref.Name, StringComparison.CurrentCultureIgnoreCase)); - return value != null ? (key, value) : default; - } - private (int idx, VeinArgumentRef type)? getArg(FieldName @ref) - { - var result = Arguments.Select((x, i) => (i, x)).FirstOrDefault(x => x.x.Name.Equals(@ref.Name, StringComparison.CurrentCultureIgnoreCase)); - return result.x is null ? default((int idx, VeinArgumentRef type)?) : result; - } - #endregion + internal int? GetLocalIndex(FieldName @ref) + => getLocal(@ref)?.idx; + private (int idx, VeinArgumentRef arg)? getLocal(FieldName @ref) + { + var (key, value) = Locals + .FirstOrDefault(x + => x.Value.Name.Equals(@ref.Name, StringComparison.CurrentCultureIgnoreCase)); + return value != null ? (key, value) : default; } + private (int idx, VeinArgumentRef type)? getArg(FieldName @ref) + { + var result = Signature.Arguments.Select((x, i) => (i, x)).FirstOrDefault(x => x.x.Name.Equals(@ref.Name, StringComparison.CurrentCultureIgnoreCase)); + return result.x is null ? default((int idx, VeinArgumentRef type)?) : result; + } + #endregion + + public override string ToString() => $"{RawName}{Signature.ToTemplateString()}"; } diff --git a/runtime/ishtar.base/emit/ModuleReader.cs b/runtime/ishtar.base/emit/ModuleReader.cs index ee7e1023..cb695778 100644 --- a/runtime/ishtar.base/emit/ModuleReader.cs +++ b/runtime/ishtar.base/emit/ModuleReader.cs @@ -203,6 +203,25 @@ public static ModuleReader Read(byte[] arr, IReadOnlyList deps, Func module.class_table.Add(@class); } + // read aliases + foreach (var _ in ..reader.ReadInt32()) + { + var key = reader.ReadInt32(); + var name = reader.ReadIshtarString(); + var isType = reader.ReadBoolean(); + + if (isType) + { + var typename = reader.ReadTypeName(module); + module.alias_table.Add(new VeinAliasType(name, module.FindType(typename, true))); + } + else + { + var retType = reader.ReadComplexType(module); + var args = ReadArguments(reader, module); + module.alias_table.Add(new VeinAliasMethod(name, new VeinMethodSignature(retType, args))); + } + } // restore unresolved types foreach (var @class in module.class_table) diff --git a/runtime/ishtar.base/emit/VeinModuleBuilder.cs b/runtime/ishtar.base/emit/VeinModuleBuilder.cs index 1d63d99a..4340d74b 100644 --- a/runtime/ishtar.base/emit/VeinModuleBuilder.cs +++ b/runtime/ishtar.base/emit/VeinModuleBuilder.cs @@ -181,6 +181,27 @@ public byte[] BakeByteArray() binary.Write(body); } + binary.Write(alias_table.Count); + foreach (var (alias, i) in alias_table.Select((x, y) => (x,y))) + { + binary.Write(i); + binary.WriteTypeName(alias.aliasName, this); + + switch (alias) + { + case VeinAliasType t: + binary.Write(true); + binary.WriteTypeName(t.type.FullName, this); + break; + case VeinAliasMethod method: + binary.Write(false); + binary.WriteComplexType(method.method.ReturnType, this); + binary.WriteArguments(method.method, this); + break; + default: + throw new NotSupportedException(); + } + } var constBody = const_table.BakeByteArray(); binary.Write(constBody.Length); binary.Write(constBody); @@ -195,6 +216,12 @@ public string BakeDebugString() var str = new StringBuilder(); str.AppendLine($".module '{Name}'::'{Version}'"); str.AppendLine("{"); + + foreach (var value in alias_table.OfType()) + str.AppendLine($"\t.alias '{value.aliasName}' -> '{value.type.FullName}'"); + foreach (var value in alias_table.OfType()) + str.AppendLine($"\t.alias '{value.aliasName}' -> '{value.method.ToTemplateString()}'"); + foreach (var dep in Deps) str.AppendLine($"\t.dep '{dep.Name}'::'{dep.Version}'"); diff --git a/test/vc_test/Features/AliasFeatureTest.cs b/test/vc_test/Features/AliasFeatureTest.cs new file mode 100644 index 00000000..9f619a41 --- /dev/null +++ b/test/vc_test/Features/AliasFeatureTest.cs @@ -0,0 +1,36 @@ +namespace veinc_test.Features; + +public class AliasFeatureTest : TestContext +{ + [Test] + public void ClassicAlias() + { + var a1 = Syntax.AliasDeclaration.Positioned().ParseVein($"alias foo <| TestType;"); + + Assert.IsTrue(a1.IsType); + + var a2 = Syntax.AliasDeclaration.Positioned().ParseVein($"global alias foo <| TestType;"); + + Assert.IsTrue(a2.IsType); + Assert.IsTrue(a2.IsGlobal); + } + + [Test] + public void AliasForMethodDeclaration() + { + var beforeMethodTest = Syntax.MethodParametersAndBody.Token().ParseVein("(i: i32, f: String): void;"); + + + var a1 = Syntax.AliasDeclaration.Positioned().ParseVein($"alias foo <| (i: i32, f: String): void;"); + + Assert.IsFalse(a1.IsType); + Assert.IsTrue(a1.IsMethod); + + + var a2 = Syntax.AliasDeclaration.Positioned().ParseVein($"global alias foo <| (i: i32, f: String): void;"); + + Assert.IsFalse(a2.IsType); + Assert.IsTrue(a2.IsMethod); + Assert.IsTrue(a2.IsGlobal); + } +}