Skip to content

Commit 83ab2e0

Browse files
committed
#1337: Адаптация для 2.0
1 parent 604ec35 commit 83ab2e0

File tree

5 files changed

+266
-283
lines changed

5 files changed

+266
-283
lines changed
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
/*----------------------------------------------------------
2+
This Source Code Form is subject to the terms of the
3+
Mozilla Public License, v.2.0. If a copy of the MPL
4+
was not distributed with this file, You can obtain one
5+
at http://mozilla.org/MPL/2.0/.
6+
----------------------------------------------------------*/
7+
using System;
8+
using System.Collections.Generic;
9+
using OneScript.Types;
10+
using OneScript.Values;
11+
12+
namespace OneScript.StandardLibrary.TypeDescriptions
13+
{
14+
internal class TypeComparer : IComparer<BslTypeValue>
15+
{
16+
private const string TYPE_BINARYDATA_NAME = "ДвоичныеДанные";
17+
private static readonly IDictionary<TypeDescriptor, int> primitives = new Dictionary<TypeDescriptor, int>();
18+
19+
public int Compare(BslTypeValue x, BslTypeValue y)
20+
{
21+
if (x.TypeValue.Equals(y)) return 0;
22+
23+
var primitiveX = PrimitiveIndex(x);
24+
var primitiveY = PrimitiveIndex(y);
25+
26+
if (primitiveX != -1)
27+
{
28+
if (primitiveY != -1)
29+
return primitiveX - primitiveY;
30+
31+
return -1;
32+
}
33+
34+
if (primitiveY != -1)
35+
return 1;
36+
37+
return x.TypeValue.Id.CompareTo(y.TypeValue.Id);
38+
}
39+
40+
private int PrimitiveIndex(BslTypeValue type)
41+
{
42+
if (StringComparer.CurrentCultureIgnoreCase.Equals(type.TypeValue.Name, TYPE_BINARYDATA_NAME))
43+
{
44+
// Пора двоичным данным стать примитивом
45+
return 1;
46+
}
47+
48+
if (primitives.TryGetValue(type.TypeValue, out var index))
49+
return index;
50+
51+
return -1;
52+
}
53+
54+
static TypeComparer()
55+
{
56+
primitives.Add(BasicTypes.Boolean, 0);
57+
primitives.Add(BasicTypes.String, 2);
58+
primitives.Add(BasicTypes.Date, 3);
59+
primitives.Add(BasicTypes.Null, 4);
60+
primitives.Add(BasicTypes.Number, 5);
61+
primitives.Add(BasicTypes.Type, 6);
62+
}
63+
64+
}
65+
}
66+

src/OneScript.StandardLibrary/TypeDescriptions/TypeDescription.cs

Lines changed: 149 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -89,12 +89,21 @@ internal IEnumerable<BslTypeValue> TypesInternal()
8989
public bool ContainsType(IValue type)
9090
{
9191
if (type is BslTypeValue typeVal)
92+
{
93+
if (typeVal.TypeValue.Equals(BasicTypes.Undefined))
94+
{
95+
// тип "Неопределено" содержится в любом явно определенном составном типе
96+
// и не содержится в типе Произвольный (когда явно не указан состав типов)
97+
// или когда указан один конкретный тип
98+
return (_types.Count > 1);
99+
}
92100
return _types.Contains(typeVal);
101+
}
93102

94103
throw RuntimeException.InvalidArgumentType(nameof(type));
95104
}
96105

97-
IValueAdjuster GetAdjusterForType(BslTypeValue type)
106+
private IValueAdjuster GetAdjusterForType(BslTypeValue type)
98107
{
99108
var value = type.TypeValue;
100109

@@ -110,6 +119,9 @@ IValueAdjuster GetAdjusterForType(BslTypeValue type)
110119
if (value.Equals(BasicTypes.Boolean))
111120
return new BooleanTypeAdjuster();
112121

122+
if (value.Equals(BasicTypes.Undefined))
123+
return new UndefinedTypeAdjuster();
124+
113125
return null;
114126
}
115127

@@ -122,16 +134,15 @@ public IValue AdjustValue(IValue pValue = null)
122134
return value ?? ValueFactory.Create();
123135
}
124136

125-
if (value != null && value.SystemType != BasicTypes.Undefined)
137+
if (value != null)
126138
{
127139
var valueType = new BslTypeValue(value.SystemType);
128-
if (_types.Contains(valueType))
140+
if (ContainsType(valueType))
129141
{
130142
// Если такой тип у нас есть
131143
var adjuster = GetAdjusterForType(valueType);
132-
var adjustedValue = adjuster.Adjust(value);
133-
if (adjustedValue != null)
134-
return adjustedValue;
144+
var adjustedValue = adjuster?.Adjust(value) ?? value;
145+
return adjustedValue;
135146
}
136147
}
137148

@@ -146,41 +157,25 @@ public IValue AdjustValue(IValue pValue = null)
146157
return ValueFactory.Create();
147158
}
148159

149-
internal static BslTypeValue TypeNumber()
150-
{
151-
return new BslTypeValue(BasicTypes.Number);
152-
}
153-
154-
internal static BslTypeValue TypeBoolean()
155-
{
156-
return new BslTypeValue(BasicTypes.Boolean);
157-
}
158-
159-
internal static BslTypeValue TypeString()
160-
{
161-
return new BslTypeValue(BasicTypes.String);
162-
}
163-
164-
internal static BslTypeValue TypeDate()
165-
{
166-
return new BslTypeValue(BasicTypes.Date);
167-
}
168-
169160
public static TypeDescription StringType(int length = 0,
170-
AllowedLengthEnum allowedLength = AllowedLengthEnum.Variable)
161+
AllowedLengthEnum allowedLength = AllowedLengthEnum.Variable)
171162
{
172-
return TypeDescriptionBuilder.Build(TypeString(), new StringQualifiers(length, allowedLength));
163+
return TypeDescriptionBuilder.OfType(BasicTypes.String)
164+
.SetStringQualifiers(new StringQualifiers(length, allowedLength))
165+
.Build();
173166
}
174167

175168
public static TypeDescription IntegerType(int length = 10,
176-
AllowedSignEnum allowedSign = AllowedSignEnum.Any)
169+
AllowedSignEnum allowedSign = AllowedSignEnum.Any)
177170
{
178-
return TypeDescriptionBuilder.Build(TypeNumber(), new NumberQualifiers(length, 0, allowedSign));
171+
return TypeDescriptionBuilder.OfType(BasicTypes.Number)
172+
.SetNumberQualifiers(new NumberQualifiers(length, 0, allowedSign))
173+
.Build();
179174
}
180175

181176
public static TypeDescription BooleanType()
182177
{
183-
return TypeDescriptionBuilder.Build(TypeBoolean());
178+
return TypeDescriptionBuilder.OfType(BasicTypes.Boolean).Build();
184179
}
185180

186181
[ScriptConstructor]
@@ -194,71 +189,156 @@ public static TypeDescription Constructor(
194189
IValue p6 = null,
195190
IValue p7 = null)
196191
{
192+
var builder = new TypeDescriptionBuilder();
193+
194+
// параметры, которые заведомо не квалификаторы, заменяем на null, но оставляем,
195+
// чтобы указать номер параметра при выводе ошибки несоответствия типа
196+
var qualifiers = new[] { null, p2, p3, p4, p5, p6, p7 };
197+
197198
var rawSource = source?.GetRawValue();
198-
199199
if (rawSource == null || rawSource.SystemType == BasicTypes.Undefined)
200200
{
201201
// пустой первый параметр - нет объекта-основания
202202
// добавляемые/вычитаемые типы не допускаются, квалификаторы игнорируются
203203

204204
// квалификакторы передаются только для контроля типов
205-
return ConstructByQualifiers(context.TypeManager, BslUndefinedValue.Instance, p2, p3, p4, p5, p6, p7);
206205
}
207-
208-
if (rawSource is TypeDescription)
206+
else
207+
if (rawSource is TypeDescription typeDesc)
209208
{
210-
return ConstructByOtherDescription(context.TypeManager, rawSource, p2, p3, p4, p5, p6, p7);
211-
}
209+
// Если 1 парарметр - ОписаниеТипов, то 2 - добавляемые типы, 3 - убираемые типы,
210+
builder.SourceDescription(typeDesc);
211+
212+
var typesToAdd = CheckAndParseTypeList(context.TypeManager, p2, 2);
213+
var typesToRemove = CheckAndParseTypeList(context.TypeManager, p3, 3);
214+
215+
builder.RemoveTypes(typesToRemove);
216+
builder.AddTypes(typesToAdd);
212217

218+
qualifiers[1] = null; // эти параметры не квалификаторы
219+
qualifiers[2] = null; // эти параметры не квалификаторы
220+
221+
}
222+
else
213223
if (rawSource.SystemType == BasicTypes.String || rawSource is ArrayImpl)
214224
{
215-
return ConstructByQualifiers(context.TypeManager, rawSource, p2, p3, p4, p5, p6, p7);
225+
// Если 1 парарметр - Массив или строка, то это набор конкретных типов
226+
// остальные параметры (2 и далее) - клвалификаторы в произвольном порядке
227+
var typesList = CheckAndParseTypeList(context.TypeManager, rawSource, 1);
228+
builder.AddTypes(typesList);
229+
} else
230+
throw RuntimeException.InvalidArgumentValue();
231+
232+
CheckAndAddQualifiers(builder, qualifiers);
233+
return builder.Build();
234+
}
235+
236+
/// <summary>
237+
/// Преобразует входящий параметр в список типов.
238+
/// </summary>
239+
/// <param name="types">В качестве типов могут быть переданы Строка или Массив Типов</param>
240+
/// <param name="nParam">Номер параметра, который будет указан в исключении, если параметр typeList задан неверно</param>
241+
/// <exception cref="RuntimeException">Если typeList не может быть разобран как набор типов</exception>
242+
/// <returns>Список переданных типов, приведенный к конкретным TypeTypeValue</returns>
243+
private static List<BslTypeValue> CheckAndParseTypeList(ITypeManager typeManager, IValue types, int nParam)
244+
{
245+
types = types?.GetRawValue();
246+
if (types == null || types.SystemType == BasicTypes.Undefined)
247+
return new List<BslTypeValue>();
248+
249+
if (types.SystemType == BasicTypes.String)
250+
{
251+
return FromTypeNames(typeManager, types.AsString());
252+
}
253+
if (types is ArrayImpl arrayOfTypes)
254+
{
255+
return FromArrayOfTypes(arrayOfTypes);
216256
}
217257

218-
throw RuntimeException.InvalidArgumentValue();
258+
throw RuntimeException.InvalidNthArgumentType(nParam);
219259
}
220260

221-
private static TypeDescription ConstructByQualifiers(ITypeManager typeManager, IValue types,
222-
IValue p2 = null,
223-
IValue p3 = null,
224-
IValue p4 = null,
225-
IValue p5 = null,
226-
IValue p6 = null,
227-
IValue p7 = null)
261+
private static List<BslTypeValue> FromTypeNames(ITypeManager typeManager, string types)
228262
{
229-
var builder = new TypeDescriptionBuilder();
230-
var typesList = TypeList.Construct(typeManager, types, 1);
231-
builder.AddTypes(typesList.List());
263+
var typeNames = types.Split(',');
264+
var typesList = new List<BslTypeValue>();
265+
foreach (var typeName in typeNames)
266+
{
267+
if (string.IsNullOrWhiteSpace(typeName))
268+
continue;
232269

233-
builder.AddQualifiers(new[] { p2, p3, p4, p5, p6, p7 }, 1);
270+
var typeValue = new BslTypeValue(typeManager.GetTypeByName(typeName.Trim()));
271+
if (!typesList.Contains(typeValue))
272+
typesList.Add(typeValue);
273+
}
234274

235-
return builder.Build();
275+
return typesList;
236276
}
237277

238-
private static TypeDescription ConstructByOtherDescription(ITypeManager typeManager,
239-
IValue typeDescription = null,
240-
IValue addTypes = null,
241-
IValue removeTypes = null,
242-
IValue p4 = null,
243-
IValue p5 = null,
244-
IValue p6 = null,
245-
IValue p7 = null)
278+
private static List<BslTypeValue> FromArrayOfTypes(ArrayImpl arrayOfTypes)
246279
{
247-
var builder = new TypeDescriptionBuilder();
280+
var typesList = new List<BslTypeValue>();
281+
foreach (var type in arrayOfTypes)
282+
{
283+
if (type.GetRawValue() is BslTypeValue rawType)
284+
{
285+
typesList.Add(rawType);
286+
}
287+
}
288+
return typesList;
289+
}
248290

249-
if (typeDescription is TypeDescription typeDesc)
291+
private static void CheckAndAddQualifiers(TypeDescriptionBuilder builder, IValue[] parameters)
292+
{
293+
for (var i = 0; i < parameters.Length; i++)
250294
{
251-
builder.SourceDescription(typeDesc);
295+
var rawQualifier = parameters[i]?.GetRawValue();
296+
if (rawQualifier != null && !rawQualifier.Equals(ValueFactory.Create()))
297+
{
298+
CheckAndAddOneQualifier(builder, rawQualifier, i + 1);
299+
}
252300
}
253-
254-
var removeTypesList = TypeList.Construct(typeManager, removeTypes, 3);
255-
builder.RemoveTypes(removeTypesList.List());
301+
}
256302

257-
var addTypesList = TypeList.Construct(typeManager, addTypes, 2);
258-
builder.AddTypes(addTypesList.List());
259-
builder.AddQualifiers(new[] { p4, p5, p6, p7 }, 3);
303+
/// <summary>
304+
/// Проверяет, что переданный параметр является квалификатором типа.
305+
/// Если тип параметра не является квалификатором, бросает исключение с указанием номера параметра.
306+
/// </summary>
307+
/// <param name="builder">Построитель описания типов, которому будет присвоен квалификатор</param>
308+
/// <param name="qualifier">Проверяемый входящий параметр</param>
309+
/// <param name="nParam">Порядковый номер параметра для выброса исключения</param>
310+
/// <exception cref="RuntimeException">Если qualifier не является квалификатором типа</exception>
311+
private static void CheckAndAddOneQualifier(TypeDescriptionBuilder builder, IValue qualifier, int nParam)
312+
{
313+
switch (qualifier)
314+
{
315+
case NumberQualifiers nq:
316+
builder.SetNumberQualifiers(nq);
317+
break;
260318

261-
return builder.Build();
319+
case StringQualifiers sq:
320+
builder.SetStringQualifiers(sq);
321+
break;
322+
323+
case DateQualifiers dq:
324+
builder.SetDateQualifiers(dq);
325+
break;
326+
327+
case BinaryDataQualifiers bdq:
328+
builder.SetBinaryDataQualifiers(bdq);
329+
break;
330+
331+
default:
332+
throw RuntimeException.InvalidNthArgumentType(nParam);
333+
}
334+
}
335+
}
336+
337+
internal class UndefinedTypeAdjuster : IValueAdjuster
338+
{
339+
public IValue Adjust(IValue value)
340+
{
341+
return ValueFactory.Create();
262342
}
263343
}
264344
}

0 commit comments

Comments
 (0)