diff --git a/src2/Maja/Maja.Compiler/IR/IrBuilder.cs b/src2/Maja/Maja.Compiler/IR/IrBuilder.cs index 88ada3b..02fb230 100644 --- a/src2/Maja/Maja.Compiler/IR/IrBuilder.cs +++ b/src2/Maja/Maja.Compiler/IR/IrBuilder.cs @@ -188,12 +188,14 @@ private IrDeclarationType DeclarationType(TypeDeclarationSyntax syntax) _diagnostics.TypeAlreadyDeclared(syntax.Location, syntax.Name.Text); } + var baseType = Type(syntax.BaseType); + // TODO: inline declared types var locality = CurrentScope.IsExport(name) || syntax.IsPublic ? IrLocality.Public : IrLocality.None; - return new IrDeclarationType(syntax, symbol, typeParameters, enums, fields, rules, typeScope, locality); + return new IrDeclarationType(syntax, symbol, typeParameters, enums, fields, rules, baseType, typeScope, locality); } private IEnumerable TypeMemberEnums(TypeMemberListSyntax? syntax) diff --git a/src2/Maja/Maja.Compiler/IR/IrDeclaration.cs b/src2/Maja/Maja.Compiler/IR/IrDeclaration.cs index 30aeaee..e087d98 100644 --- a/src2/Maja/Maja.Compiler/IR/IrDeclaration.cs +++ b/src2/Maja/Maja.Compiler/IR/IrDeclaration.cs @@ -89,11 +89,13 @@ public IEnumerable GetDescendentsOfType() where T : IrNode internal sealed class IrDeclarationType : IrDeclaration, IrContainer { public IrDeclarationType(TypeDeclarationSyntax syntax, TypeSymbol symbol, IEnumerable typeParameters, - IEnumerable enums, IEnumerable fields, IEnumerable rules, IrTypeScope scope, IrLocality locality) + IEnumerable enums, IEnumerable fields, IEnumerable rules, + IrType? baseType, IrTypeScope scope, IrLocality locality) : base(syntax, locality) { Symbol = symbol; Scope = scope; + BaseType = baseType; TypeParameters = typeParameters.ToImmutableArray(); Enums = enums.ToImmutableArray(); Fields = fields.ToImmutableArray(); @@ -102,6 +104,7 @@ public IrDeclarationType(TypeDeclarationSyntax syntax, TypeSymbol symbol, IEnume public TypeSymbol Symbol { get; } public IrTypeScope Scope { get; } + public IrType? BaseType { get; } public ImmutableArray TypeParameters { get; } public ImmutableArray Enums { get; } public ImmutableArray Fields { get; } diff --git a/src2/Maja/Maja.Compiler/IR/IrRewriter.cs b/src2/Maja/Maja.Compiler/IR/IrRewriter.cs index 68e13e8..bbfc6be 100644 --- a/src2/Maja/Maja.Compiler/IR/IrRewriter.cs +++ b/src2/Maja/Maja.Compiler/IR/IrRewriter.cs @@ -145,14 +145,16 @@ protected virtual IrDeclarationType RewriteDeclarationType(IrDeclarationType typ var enums = RewriteEnums(type.Enums); var fields = RewriteFields(type.Fields); var rules = RewriteRules(type.Rules); + var baseType = RewriteType(type.BaseType); if (typeParams == type.TypeParameters && enums == type.Enums && fields == type.Fields && - rules == type.Rules) + rules == type.Rules && + baseType == type.BaseType) return type; - return new IrDeclarationType(type.Syntax, type.Symbol, typeParams, enums, fields, rules, type.Scope, type.Locality); + return new IrDeclarationType(type.Syntax, type.Symbol, typeParams, enums, fields, rules, baseType, type.Scope, type.Locality); } protected virtual ImmutableArray RewriteEnums(ImmutableArray memberEnums) diff --git a/src2/Maja/Maja.Compiler/Syntax/TypeDeclarationSyntax.cs b/src2/Maja/Maja.Compiler/Syntax/TypeDeclarationSyntax.cs index 8169829..187c732 100644 --- a/src2/Maja/Maja.Compiler/Syntax/TypeDeclarationSyntax.cs +++ b/src2/Maja/Maja.Compiler/Syntax/TypeDeclarationSyntax.cs @@ -21,6 +21,12 @@ public override SyntaxKind SyntaxKind public NameSyntax Name => ChildNodes.OfType().Single(); + /// + /// Optional base type. + /// + public TypeSyntax? BaseType + => ChildNodes.OfType().SingleOrDefault(); + /// /// The type parameters, if any. /// diff --git a/src2/Maja/Maja.Compiler/readme.md b/src2/Maja/Maja.Compiler/readme.md index efe4f8e..418aaa0 100644 --- a/src2/Maja/Maja.Compiler/readme.md +++ b/src2/Maja/Maja.Compiler/readme.md @@ -1,4 +1,4 @@ -# Maja Compiler + # Maja Compiler ## TODO @@ -9,11 +9,12 @@ Started. Have ErrorToken with description. - [ ] Syntax: Assignment to member access expression (l-value) (now nameIdentifier) - [ ] Syntax: serialze Syntax model into Maja code. Should be the exact same as source. - [ ] Indents (dedent) are not working correct with multiple indents (`SyntaxWriter`). -- [ ] Type: base type (enum/struct/value) -- [ ] Type: Generics +- [ ] Type: base type (enum/struct/value). + - [ ] Resolve base types of derived types. +- [ ] Type: Generics (type inference) - [ ] Type: Template - [ ] Type: Comp-parameter -- [ ] Function: Generics +- [ ] Function: Generics (type inference) - [ ] Function: Template - [ ] Function: Comp-parameter - [ ] Value (custom) Types (/w rules) @@ -76,4 +77,4 @@ Only necessary when tree is allowed to change. ## Notes -- CodeBlock is a statement or an expression? +- Is CodeBlock a statement or an expression? diff --git a/src2/Maja/Maja.UnitTests/Compiler/IR/TypeTests.cs b/src2/Maja/Maja.UnitTests/Compiler/IR/TypeTests.cs index c4ea841..05b0b9c 100644 --- a/src2/Maja/Maja.UnitTests/Compiler/IR/TypeTests.cs +++ b/src2/Maja/Maja.UnitTests/Compiler/IR/TypeTests.cs @@ -56,6 +56,39 @@ public void TypeDeclareFields() type.Fields[1].Type.Symbol.Should().Be(TypeSymbol.Str); } + [Fact] + public void TypeDeclareFields_BaseType() + { + const string code = + "BaseType" + Tokens.Eol + + Tokens.Indent1 + "fld1: U8" + Tokens.Eol + + "MyType : BaseType" + Tokens.Eol + + Tokens.Indent1 + "fld2: Str" + Tokens.Eol + ; + + var program = Ir.Build(code); + program.Root.Should().NotBeNull(); + program.Root.Declarations.Should().HaveCount(2); + var baseType = program.Root.Declarations[0].As(); + var symbol = baseType.Symbol.As(); + symbol.Name.Value.Should().Be("Basetype"); + symbol.Fields.Should().HaveCount(1); + baseType.Fields.Should().HaveCount(1); + baseType.Fields[0].DefaultValue.Should().BeNull(); + baseType.Fields[0].Symbol.Name.Value.Should().Be("fld1"); + baseType.Fields[0].Type.Symbol.Should().Be(TypeSymbol.U8); + + var type = program.Root.Declarations[1].As(); + type.BaseType!.Symbol.Name.Value.Should().Be("Basetype"); + symbol = type.Symbol.As(); + symbol.Name.Value.Should().Be("Mytype"); + symbol.Fields.Should().HaveCount(1); + type.Fields.Should().HaveCount(1); + type.Fields[0].DefaultValue.Should().BeNull(); + type.Fields[0].Symbol.Name.Value.Should().Be("fld2"); + type.Fields[0].Type.Symbol.Should().Be(TypeSymbol.Str); + } + [Fact] public void TypeDeclareFields_Generics() { diff --git a/src2/Maja/Maja.UnitTests/Compiler/Syntax/TypeSyntaxTests.cs b/src2/Maja/Maja.UnitTests/Compiler/Syntax/TypeSyntaxTests.cs index fe19bbf..d0d174a 100644 --- a/src2/Maja/Maja.UnitTests/Compiler/Syntax/TypeSyntaxTests.cs +++ b/src2/Maja/Maja.UnitTests/Compiler/Syntax/TypeSyntaxTests.cs @@ -34,6 +34,24 @@ public void TypeDeclareStruct() Syntax.RoundTrip(code, _output); } + [Fact] + public void TypeDeclareStruct_Derived() + { + const string code = + "Type : BaseType" + Tokens.Eol + + Tokens.Indent1 + "fld1: U8" + Tokens.Eol + ; + + var result = Syntax.Parse(code); + result.Members.Should().HaveCount(1); + var t = result.Members.First().As(); + t.Name.Text.Should().Be("Type"); + t.BaseType.Should().NotBeNull(); + t.BaseType!.Name.Text.Should().Be("BaseType"); + + Syntax.RoundTrip(code, _output); + } + [Fact] public void TypeDeclareStruct_Generics() { diff --git a/src2/Maja/Maja.UnitTests/readme.md b/src2/Maja/Maja.UnitTests/readme.md index 76570a8..625cd2d 100644 --- a/src2/Maja/Maja.UnitTests/readme.md +++ b/src2/Maja/Maja.UnitTests/readme.md @@ -65,14 +65,15 @@ Keeping track of the progress of Maja features. |Feature | |Grammar|Syntax|Ir|Checks|Lower|Repl|Emit|Runtime|Description| |-------------|-----|:-:|:-:|:-:|:-:|:-:|:-:|:-:|---|---------------| -| struct | | x | x | x | | | x | x | | `MyType -> fld: U8` | +| struct | flds | x | x | x | | | x | x | | `MyType -> fld: U8` | | | enum | x | x | | | | | | | `MyType -> fld: U8 -> Opt1, Opt2` | +| | init | x | x | x | | | x | x | | `MyType -> fld = 42` | | generics | | x | x | x | | | | | | `MyType -> fld: T` | | template | | x | x | | | | | | | `MyType<#T> -> fld: T` | | enum | | x | x | x | | | | x | | `MyType -> opt1, opt2` | | custom | | | | | | | | | | `MyType: U8` | | rule | | | | | | | | | | `MyType -> #fld1 > 0` | -| struct | init | x | x | x | | | x | x | | `MyType -> fld = 42` | +| baseType | flds | x | x | x | | | | | | `MyType : BaseType` | ## Expressions