Skip to content

Commit

Permalink
Merge pull request #296 from betwixt-labs/mut-modifier
Browse files Browse the repository at this point in the history
feat: mut modifier
  • Loading branch information
andrewmd5 authored Jan 21, 2024
2 parents b0f7692 + 65d3c8d commit 02e4e2f
Show file tree
Hide file tree
Showing 10 changed files with 28 additions and 32 deletions.
4 changes: 2 additions & 2 deletions Core/Generators/CSharp/CSharpGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ public override ValueTask<string> Compile(BebopSchema schema, GeneratorConfig co
var recordAttribute = fd switch
{
MessageDefinition => "[global::Bebop.Attributes.BebopRecord(global::Bebop.Runtime.BebopKind.Message)]",
StructDefinition { IsReadOnly: true } => "[global::Bebop.Attributes.BebopRecord(global::Bebop.Runtime.BebopKind.Struct, true)]",
StructDefinition { IsMutable: true } => "[global::Bebop.Attributes.BebopRecord(global::Bebop.Runtime.BebopKind.Struct, true)]",
StructDefinition => "[global::Bebop.Attributes.BebopRecord(global::Bebop.Runtime.BebopKind.Struct)]",
_ => string.Empty
};
Expand Down Expand Up @@ -161,7 +161,7 @@ public override ValueTask<string> Compile(BebopSchema schema, GeneratorConfig co
}
var type = TypeName(field.Type, string.Empty);
var opt = fd is MessageDefinition && IsNullableType(field.Type) ? "?" : "";
var setOrInit = fd is StructDefinition { IsReadOnly: true } ? LanguageVersion == CSharpNine ? "init" : "private set" : "set";
var setOrInit = fd is StructDefinition { IsMutable: false } ? LanguageVersion == CSharpNine ? "init" : "private set" : "set";
builder.AppendLine($"public {type}{opt} {field.Name.ToPascalCase()} {{ get; {setOrInit}; }}");
}

Expand Down
4 changes: 2 additions & 2 deletions Core/Generators/Dart/DartGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -351,7 +351,7 @@ public override ValueTask<string> Compile(BebopSchema schema, GeneratorConfig co
{
builder.AppendLine($" /// @deprecated {reason}");
}
var final = fd is StructDefinition { IsReadOnly: true } ? "final " : "";
var final = fd is StructDefinition { IsMutable: false } ? "final " : "";
var optional = fd is MessageDefinition ? "?" : "";
builder.AppendLine($" {final}{type}{optional} {field.Name};");
}
Expand All @@ -361,7 +361,7 @@ public override ValueTask<string> Compile(BebopSchema schema, GeneratorConfig co
}
else
{
builder.AppendLine($" {(fd is StructDefinition { IsReadOnly: true } ? "const " : "")}{fd.Name}({{");
builder.AppendLine($" {(fd is StructDefinition { IsMutable: false } ? "const " : "")}{fd.Name}({{");
foreach (var field in fd.Fields)
{
builder.AppendLine($" required this.{field.Name},");
Expand Down
2 changes: 1 addition & 1 deletion Core/Generators/GeneratorContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -260,7 +260,7 @@ private static void WriteStruct(StructDefinition sd, BebopSchema schema, Utf8Jso
{
writer.WriteNumber("discriminatorInParent", sd.DiscriminatorInParent.Value);
}
writer.WriteBoolean("readonly", sd.IsReadOnly);
writer.WriteBoolean("mutable", sd.IsMutable);
writer.WriteBoolean("isFixedSize", sd.IsFixedSize(schema));
var fieldCount = sd.Fields.Count;
if (fieldCount < 0 || fieldCount > byte.MaxValue)
Expand Down
6 changes: 3 additions & 3 deletions Core/Generators/Python/PythonGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -385,8 +385,8 @@ public override ValueTask<string> Compile(BebopSchema schema, GeneratorConfig co
builder.Append(FormatDocumentation(definition.Documentation, null));
builder.AppendLine();
}
var isReadonlyStruct = rd is StructDefinition sd ? sd.IsReadOnly : false;
var fieldPrepend = isReadonlyStruct ? "_" : "";
var isMutableStruct = rd is StructDefinition sd && sd.IsMutable;
var fieldPrepend = !isMutableStruct ? "_" : "";
for (var i = 0; i < fd.Fields.Count; i++)
{
var field = fd.Fields.ElementAt(i);
Expand Down Expand Up @@ -441,7 +441,7 @@ public override ValueTask<string> Compile(BebopSchema schema, GeneratorConfig co
}, open: string.Empty, close: string.Empty);
}

if (isReadonlyStruct)
if (!isMutableStruct)
{
for (var i = 0; i < fd.Fields.Count; i++)
{
Expand Down
4 changes: 2 additions & 2 deletions Core/Generators/TypeScript/TypeScriptGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -733,7 +733,7 @@ public override ValueTask<string> Compile(BebopSchema schema, GeneratorConfig co
var type = TypeName(field.Type);
builder.AppendLine(FormatDocumentation(field.Documentation, field.DeprecatedDecorator, 2));

builder.AppendLine($" {(fd is StructDefinition { IsReadOnly: true } ? "readonly " : "")}{field.NameCamelCase}{(fd is MessageDefinition ? "?" : "")}: {type};");
builder.AppendLine($" {(fd is StructDefinition { IsMutable: false } ? "readonly " : string.Empty)}{field.NameCamelCase}{(fd is MessageDefinition ? "?" : "")}: {type};");
}
builder.AppendLine("}");
builder.AppendLine();
Expand All @@ -752,7 +752,7 @@ public override ValueTask<string> Compile(BebopSchema schema, GeneratorConfig co
{
var field = fd.Fields.ElementAt(i);
var type = TypeName(field.Type);
builder.AppendLine($"public {(fd is StructDefinition { IsReadOnly: true } ? "readonly " : "")}{field.NameCamelCase}{(fd is MessageDefinition ? "?" : "")}: {type};");
builder.AppendLine($"public {(fd is StructDefinition { IsMutable: false } ? "readonly " : string.Empty)}{field.NameCamelCase}{(fd is MessageDefinition ? "?" : string.Empty)}: {type};");

}
builder.AppendLine();
Expand Down
2 changes: 1 addition & 1 deletion Core/IO/BinarySchemaWriter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -327,7 +327,7 @@ private void WriteEnum(EnumDefinition definition)
private void WriteStruct(StructDefinition definition)
{
// modifier(s)
_writer.Write(definition.IsReadOnly);
_writer.Write(definition.IsMutable);
_writer.Write(definition.MinimalEncodedSize(_schema));
_writer.Write(definition.IsFixedSize(_schema));

Expand Down
4 changes: 2 additions & 2 deletions Core/Lexer/Tokenization/TokenKind.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ public enum TokenKind : ushort
/// <summary>
/// The 'readonly' keyword which is reserved by the compiler
/// </summary>
[Keyword("readonly")]
ReadOnly,
[Keyword("mut")]
Mut,

/// <summary>
/// The 'map' keyword which is reserved by the compiler
Expand Down
6 changes: 3 additions & 3 deletions Core/Meta/Definition.cs
Original file line number Diff line number Diff line change
Expand Up @@ -121,16 +121,16 @@ public override IEnumerable<string> Dependencies() =>
/// </summary>
public class StructDefinition : FieldsDefinition
{
public StructDefinition(string name, Span span, string documentation, List<SchemaDecorator> decorators, ICollection<Field> fields, bool isReadOnly, Definition? parent = null) :
public StructDefinition(string name, Span span, string documentation, List<SchemaDecorator> decorators, ICollection<Field> fields, bool isMutable, Definition? parent = null) :
base(name, span, documentation, decorators, fields, parent)
{
IsReadOnly = isReadOnly;
IsMutable = isMutable;
}

/// <summary>
/// Is this struct "read-only"? (This will mean something like: not generating setters in the codegen.)
/// </summary>
public bool IsReadOnly { get; }
public bool IsMutable { get; }

override public int MinimalEncodedSize(BebopSchema schema)
{
Expand Down
20 changes: 8 additions & 12 deletions Core/Parser/SchemaParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -371,11 +371,7 @@ public BebopSchema Parse()
_errors.Add(e);
}
var readonlySpan = CurrentToken.Span;
var isReadOnly = Eat(TokenKind.ReadOnly);
if (isReadOnly)
{
_warnings.Add(new DeprecatedFeatureWarning(readonlySpan, "the 'readonly' modifier will be removed in the next major version of Bebop; structs will be immutable by default, and the 'mut' modifier will be added to make them mutable."));
}
var isMutable = Eat(TokenKind.Mut);
ExpectAndSkip(_topLevelDefinitionKinds, _universalFollowKinds, hint: "Expecting a top-level definition.");
if (CurrentToken.Kind == TokenKind.EndOfFile)
{
Expand All @@ -384,9 +380,9 @@ public BebopSchema Parse()
}
if (Eat(TokenKind.Service))
{
if (isReadOnly)
if (isMutable)
{
throw new UnexpectedTokenException(TokenKind.Service, CurrentToken, "Did not expect service definition after readonly. (Services are not allowed to be readonly).");
throw new UnexpectedTokenException(TokenKind.Service, CurrentToken, "Did not expect service definition after 'mut' modifier. (Services are not allowed to be mutable).");
}
if (decorators.Any((a) => a.Identifier == "opcode"))
{
Expand Down Expand Up @@ -427,7 +423,7 @@ _ when Eat(TokenKind.Message) => AggregateKind.Message,
// Uh oh we skipped ahead due to a missing identifier, get outta there
return null;
}
return ParseNonUnionDefinition(CurrentToken, kind, isReadOnly, definitionDocumentation, decorators);
return ParseNonUnionDefinition(CurrentToken, kind, isMutable, definitionDocumentation, decorators);
}
}

Expand Down Expand Up @@ -691,12 +687,12 @@ private Literal ParseLiteral(TypeBase type)
/// </summary>
/// <param name="definitionToken">The token that names the type to define.</param>
/// <param name="kind">The <see cref="AggregateKind"/> the type will represents.</param>
/// <param name="isReadOnly"></param>
/// <param name="isMutable"></param>
/// <param name="definitionDocumentation"></param>
/// <returns>The parsed definition.</returns>
private Definition? ParseNonUnionDefinition(Token definitionToken,
AggregateKind kind,
bool isReadOnly,
bool isMutable,
string definitionDocumentation,
List<SchemaDecorator> definitionDecorators)
{
Expand Down Expand Up @@ -872,12 +868,12 @@ private Literal ParseLiteral(TypeBase type)
Definition definition = kind switch
{
AggregateKind.Enum => new EnumDefinition(name, definitionSpan, definitionDocumentation, fields, definitionDecorators, enumBaseType),
AggregateKind.Struct => new StructDefinition(name, definitionSpan, definitionDocumentation, definitionDecorators, fields, isReadOnly),
AggregateKind.Struct => new StructDefinition(name, definitionSpan, definitionDocumentation, definitionDecorators, fields, isMutable),
AggregateKind.Message => new MessageDefinition(name, definitionSpan, definitionDocumentation, definitionDecorators, fields),
_ => throw new InvalidOperationException("invalid kind when making definition"),
};

if (isReadOnly && definition is not StructDefinition)
if (isMutable && definition is not StructDefinition)
{
_errors.Add(new InvalidReadOnlyException(definition));
}
Expand Down
8 changes: 4 additions & 4 deletions Runtime/C#/Attributes/BebopRecordAttribute.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,17 @@ public class BebopRecordAttribute : Attribute
/// Creates a new <see cref="BebopRecord"/> attribute.
/// </summary>
/// <param name="kind">The kind of the decorated type.</param>
/// <param name="isReadOnly">Whether or not the type record is read-only.</param>
public BebopRecordAttribute(BebopKind kind, bool isReadOnly = false)
/// <param name="isMutable">Whether or not the type record is mutable.</param>
public BebopRecordAttribute(BebopKind kind, bool isMutable = false)
{
Kind = kind;
IsReadOnly = isReadOnly;
IsMutable = isMutable;
}

/// <summary>
/// Indicates if the decorated type is read-only.
/// </summary>
public bool IsReadOnly { get; set; }
public bool IsMutable { get; set; }

/// <summary>
/// Indicates the kind of the decorated type.
Expand Down

0 comments on commit 02e4e2f

Please sign in to comment.