Skip to content

Commit 8f9f9d1

Browse files
committed
SIFOSC、全てのオブジェクトを列挙できる様にした。
1 parent 6f893f4 commit 8f9f9d1

File tree

3 files changed

+127
-32
lines changed

3 files changed

+127
-32
lines changed

FastChatProtocolInterface/SimpleFormulaScript/SifoscObject.cs

Lines changed: 112 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -7,42 +7,49 @@
77

88
using System;
99
using System.Collections.Concurrent;
10-
using System.Diagnostics;
10+
using System.Collections.Generic;
1111
using System.Text;
1212
using System.Threading;
1313

1414
namespace FastChatProtocolInterface.SimpleFormulaScript
1515
{
1616
public record SifoscObject
1717
{
18-
private static readonly ConcurrentDictionary<ulong, SifoscObject> _objects = new();
19-
private static ulong _next_id = 2;
18+
private static readonly ConcurrentDictionary<ulong, SifoscObject> _objects = [];
19+
private static ulong _next_id = 3;
2020

21-
public ulong Identifier { get; }
21+
public ulong Identifier { get; }
22+
public virtual string Code => "newobj";
2223

2324
public SifoscObject()
2425
{
25-
switch (this) {
26-
case SifoscNull:
27-
this.Identifier = 0;
28-
break;
29-
case SifoscBoolean b when b.Value:
30-
this.Identifier = 1;
31-
break;
32-
case SifoscBoolean:
33-
this.Identifier = 2;
34-
break;
35-
default:
36-
do {
37-
this.Identifier = Interlocked.Increment(ref _next_id);
38-
} while (!_objects.TryAdd(this.Identifier, this));
39-
break;
40-
}
26+
this.Identifier = this.CreateIdentifier();
27+
}
28+
29+
protected SifoscObject(SifoscObject _)
30+
{
31+
this.Identifier = this.CreateIdentifier();
32+
}
4133

42-
bool succeeded = _objects.TryAdd(this.Identifier, this);
43-
Debug.Assert(succeeded);
34+
private ulong CreateIdentifier()
35+
{
36+
ulong? id = null;
37+
38+
do {
39+
id = this switch {
40+
SifoscNull => id is null ? 0UL : throw new InvalidOperationException(),
41+
SifoscViewForAllObjects => id is null ? 1UL : throw new InvalidOperationException(),
42+
SifoscBoolean => id is null ? 2UL : id == 2 ? 3UL : throw new InvalidOperationException(),
43+
_ => Interlocked.Increment(ref _next_id)
44+
};
45+
} while (!_objects.TryAdd(id.Value, this));
46+
47+
return id.Value;
4448
}
4549

50+
public static IEnumerable<SifoscObject> EnumerateAllObjects()
51+
=> _objects.Values;
52+
4653
public virtual SifoscObject? Plus () => null;
4754
public virtual SifoscObject? Minus () => null;
4855
public virtual SifoscObject? Add (SifoscObject? other) => null;
@@ -54,6 +61,30 @@ public SifoscObject()
5461

5562
public sealed record SifoscArray : SifoscObject
5663
{
64+
public override string Code
65+
{
66+
get
67+
{
68+
var sb = new StringBuilder();
69+
var span = this.Values.Span;
70+
71+
sb.Append('[');
72+
for (int i = 0; i < span.Length; ++i) {
73+
var obj = span[i];
74+
if (obj is null) {
75+
continue;
76+
}
77+
if (i != 0) {
78+
sb.Append(',');
79+
}
80+
sb.Append(obj.Code);
81+
}
82+
sb.Append(']');
83+
84+
return sb.ToString();
85+
}
86+
}
87+
5788
public ReadOnlyMemory<SifoscObject?> Values { get; init; }
5889

5990
protected override bool PrintMembers(StringBuilder builder)
@@ -64,12 +95,18 @@ protected override bool PrintMembers(StringBuilder builder)
6495

6596
var s = this.Values.Span;
6697
for (int i = 0; i < s.Length; ++i) {
67-
if (i != 0 || appendComma) {
98+
if (appendComma) {
6899
builder.Append(", ");
69100
}
70-
builder.Append(s[i]);
101+
var obj = s[i];
102+
if (obj is SifoscViewForAllObjects view) {
103+
view.PrintMembersSimply(builder);
104+
} else {
105+
builder.Append(obj);
106+
}
107+
appendComma = true;
71108
}
72-
return s.Length > 0;
109+
return appendComma;
73110
}
74111

75112
public override SifoscObject? Add(SifoscObject? other)
@@ -97,27 +134,71 @@ public sealed record SifoscNull : SifoscObject
97134
{
98135
private static readonly SifoscNull _inst = new();
99136

100-
public static SifoscNull Instance => _inst;
137+
public static SifoscNull Instance => _inst;
138+
public override string Code => "null";
101139

102140
private SifoscNull() { }
103141
}
104142

143+
public sealed record SifoscViewForAllObjects : SifoscObject
144+
{
145+
private static readonly SifoscViewForAllObjects _inst = new();
146+
147+
public static SifoscViewForAllObjects Instance => _inst;
148+
public override string Code => "allobj";
149+
150+
private SifoscViewForAllObjects() { }
151+
152+
protected override bool PrintMembers(StringBuilder builder)
153+
{
154+
bool appendComma = base.PrintMembers(builder);
155+
156+
foreach (var item in EnumerateAllObjects()) {
157+
if (appendComma) {
158+
builder.Append(", ");
159+
}
160+
if (item is SifoscViewForAllObjects) {
161+
this.PrintMembersSimply(builder);
162+
} else {
163+
builder.Append(item);
164+
}
165+
appendComma = true;
166+
}
167+
168+
return appendComma;
169+
}
170+
171+
public void PrintMembersSimply(StringBuilder builder)
172+
{
173+
builder
174+
.Append(nameof(SifoscViewForAllObjects))
175+
.Append(" { ");
176+
177+
if (base.PrintMembers(builder)) {
178+
builder.Append(' ');
179+
}
180+
181+
builder.Append('}');
182+
}
183+
}
184+
105185
public sealed record SifoscBoolean : SifoscObject
106186
{
107187
private static readonly SifoscBoolean _true = new();
108188
private static readonly SifoscBoolean _false = new();
109189

110-
public static SifoscBoolean TrueValue => _true;
111-
public static SifoscBoolean FalseValue => _false;
112-
113-
public bool Value => ReferenceEquals(this, _true);
190+
public static SifoscBoolean TrueValue => _true;
191+
public static SifoscBoolean FalseValue => _false;
192+
public bool Value => ReferenceEquals(this, _true);
193+
public override string Code => this.Value ? "true" : "false";
114194

115195
private SifoscBoolean() { }
116196
}
117197

118198
public sealed record SifoscInteger : SifoscObject
119199
{
120-
public long Value { get; init; }
200+
public long Value { get; init; }
201+
public override string Code => this.Value.ToString();
121202

122203
public override SifoscObject? Plus()
123204
=> this;

FastChatProtocolInterface/SimpleFormulaScript/SifoscParser.cs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,9 @@ public static bool TryParseValueLiteral(this SourceCode sc, [NotNullWhen(true)][
191191
} else if (sc.TryParseNewObjectLiteral(out var objVal)) {
192192
result = objVal;
193193
return true;
194+
} else if (sc.TryParseAllObjectsLiteral(out var allVal)) {
195+
result = allVal;
196+
return true;
194197
} else if (sc.TryParseBooleanLiteral(out var flgVal)) {
195198
result = flgVal;
196199
return true;
@@ -254,6 +257,17 @@ public static bool TryParseNewObjectLiteral(this SourceCode sc, [NotNullWhen(tru
254257
}
255258
}
256259

260+
public static bool TryParseAllObjectsLiteral(this SourceCode sc, [NotNullWhen(true)][MaybeNullWhen(false)] out SifoscViewForAllObjects? result)
261+
{
262+
if (sc.TryScanKeyword("allobj")) {
263+
result = SifoscViewForAllObjects.Instance;
264+
return true;
265+
} else {
266+
result = null;
267+
return false;
268+
}
269+
}
270+
257271
public static bool TryParseBooleanLiteral(this SourceCode sc, [NotNullWhen(true)][MaybeNullWhen(false)] out SifoscBoolean? result)
258272
{
259273
if (sc.TryScanKeyword("true")) {

FastChatProtocolInterface/SimpleFormulaScript/SifoscServer.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ protected override string ReceiveMessageCore(FachpiCommunicationFlow flow)
2626

2727
public static string RunScriptLine(string s)
2828
{
29-
// SIFOSC の例:[ null, newobj, 123, +456, -789, [ ] ]
29+
// SIFOSC の例:[ [ null, allobj, true, false, newobj, 123 ], [ null, newobj, 123, +456, -789, [ ] ], [ 1, 2, 3 ] + [ 2 + 2, 5, 2 * 3 ] + [ 1 + 2 * 3 ], +-+-+-+100, ([([([])])]), 1 + ((1 + 2) * 3 + 1) / 2 % 3 - 4 ];
3030

3131
var sc = new SourceCode(s);
3232
if (sc.TryParse(out var result)) {

0 commit comments

Comments
 (0)