parent
2b464dc59a
commit
1f31c20da2
|
|
@ -2802,6 +2802,8 @@ namespace PascalABCCompiler.PCU
|
||||||
cnfn.ConnectedToType.base_type.Scope.AddSymbol(cnfn.name, new SymbolInfo(cnfn));
|
cnfn.ConnectedToType.base_type.Scope.AddSymbol(cnfn.name, new SymbolInfo(cnfn));
|
||||||
else if (cnfn.ConnectedToType != null && cnfn.ConnectedToType.is_generic_parameter)
|
else if (cnfn.ConnectedToType != null && cnfn.ConnectedToType.is_generic_parameter)
|
||||||
cnfn.ConnectedToType.base_type.Scope.AddSymbol(cnfn.name, new SymbolInfo(cnfn));
|
cnfn.ConnectedToType.base_type.Scope.AddSymbol(cnfn.name, new SymbolInfo(cnfn));
|
||||||
|
else if (cnfn.ConnectedToType is compiled_generic_instance_type_node && cnfn.ConnectedToType.original_generic.Scope != null)
|
||||||
|
cnfn.ConnectedToType.original_generic.Scope.AddSymbol(cnfn.name, new SymbolInfo(cnfn));
|
||||||
return cnfn;
|
return cnfn;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2902,6 +2904,8 @@ namespace PascalABCCompiler.PCU
|
||||||
cnfn.ConnectedToType.base_type.Scope.AddSymbol(cnfn.name, new SymbolInfo(cnfn));
|
cnfn.ConnectedToType.base_type.Scope.AddSymbol(cnfn.name, new SymbolInfo(cnfn));
|
||||||
else if (cnfn.ConnectedToType != null && cnfn.ConnectedToType.is_generic_parameter)
|
else if (cnfn.ConnectedToType != null && cnfn.ConnectedToType.is_generic_parameter)
|
||||||
cnfn.ConnectedToType.base_type.Scope.AddSymbol(cnfn.name, new SymbolInfo(cnfn));
|
cnfn.ConnectedToType.base_type.Scope.AddSymbol(cnfn.name, new SymbolInfo(cnfn));
|
||||||
|
else if (cnfn.ConnectedToType is compiled_generic_instance_type_node && cnfn.ConnectedToType.original_generic.Scope != null)
|
||||||
|
cnfn.ConnectedToType.original_generic.Scope.AddSymbol(cnfn.name, new SymbolInfo(cnfn));
|
||||||
br.BaseStream.Seek(pos,SeekOrigin.Begin);
|
br.BaseStream.Seek(pos,SeekOrigin.Begin);
|
||||||
return cnfn;
|
return cnfn;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
12
TestSuite/extensionmethods15.pas
Normal file
12
TestSuite/extensionmethods15.pas
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
function operator*<T1, T2, T3> (Self: (T1,T2); v: T3): (T1,T2,T3); extensionmethod;
|
||||||
|
begin
|
||||||
|
Result := (Self[0],Self[1],v);
|
||||||
|
end;
|
||||||
|
|
||||||
|
begin
|
||||||
|
var t0 := (1,2);
|
||||||
|
var t1 := t0 * System.DateTime.Now.DayOfWeek;
|
||||||
|
assert(t1.Item3 = System.DateTime.Now.DayOfWeek);
|
||||||
|
var s := 4+Seq(1,2,3);
|
||||||
|
assert(s.ToArray()[0]=4);
|
||||||
|
end.
|
||||||
9
TestSuite/in1.pas
Normal file
9
TestSuite/in1.pas
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
begin
|
||||||
|
var arr := Arr(1,2,3);
|
||||||
|
assert(5 in arr = false);
|
||||||
|
assert(2 in arr = true);
|
||||||
|
var l := new List<integer>();
|
||||||
|
l += 4;
|
||||||
|
l += 5;
|
||||||
|
assert(4 in l = true);
|
||||||
|
end.
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
begin
|
begin
|
||||||
{var b: byte := 2;
|
var b: byte := 2;
|
||||||
var i: integer := 3;
|
var i: integer := 3;
|
||||||
var s: shortint := 4;
|
var s: shortint := 4;
|
||||||
var w: word := 5;
|
var w: word := 5;
|
||||||
|
|
@ -12,5 +12,5 @@ begin
|
||||||
assert(min(b,lw)=2);
|
assert(min(b,lw)=2);
|
||||||
assert(min(i,lw)=3);
|
assert(min(i,lw)=3);
|
||||||
assert(min(b,i64)=2);
|
assert(min(b,i64)=2);
|
||||||
assert(min(i64,ui64)=7);}
|
assert(min(i64,ui64)=7);
|
||||||
end.
|
end.
|
||||||
29
TestSuite/overloads4.pas
Normal file
29
TestSuite/overloads4.pas
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
var a: integer;
|
||||||
|
procedure Test(p: integer);
|
||||||
|
begin
|
||||||
|
a := 1;
|
||||||
|
end;
|
||||||
|
procedure Test<T>(p: T);
|
||||||
|
begin
|
||||||
|
a := 2;
|
||||||
|
end;
|
||||||
|
procedure Test(params p: array of integer);
|
||||||
|
begin
|
||||||
|
a := 3;
|
||||||
|
end;
|
||||||
|
procedure Test<T>(params p: array of T);
|
||||||
|
begin
|
||||||
|
a := 4;
|
||||||
|
end;
|
||||||
|
begin
|
||||||
|
Test(3);
|
||||||
|
assert(a = 1);
|
||||||
|
Test('a');
|
||||||
|
assert(a = 2);
|
||||||
|
Test(byte(3));
|
||||||
|
assert(a = 2);
|
||||||
|
Test(1,2);
|
||||||
|
assert(a = 3);
|
||||||
|
Test('a','b');
|
||||||
|
assert(a = 4);
|
||||||
|
end.
|
||||||
8
TestSuite/params8.pas
Normal file
8
TestSuite/params8.pas
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
function Test<T>(a: T): sequence of T;
|
||||||
|
begin
|
||||||
|
Result := Seq(a);
|
||||||
|
end;
|
||||||
|
|
||||||
|
begin
|
||||||
|
assert(Test(2).ToArray()[0]=2);
|
||||||
|
end.
|
||||||
|
|
@ -51,4 +51,7 @@ begin
|
||||||
assert(StrToInt('234')=234);
|
assert(StrToInt('234')=234);
|
||||||
assert(StrToFloat('2.67')=2.67);
|
assert(StrToFloat('2.67')=2.67);
|
||||||
assert(IntToStr(45)='45');
|
assert(IntToStr(45)='45');
|
||||||
|
var c: char := 'a';
|
||||||
|
var o: object := 'bc';
|
||||||
|
assert(c+o='abc');
|
||||||
end.
|
end.
|
||||||
13
TestSuite/units/u_extensionmethods15.pas
Normal file
13
TestSuite/units/u_extensionmethods15.pas
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
unit u_extensionmethods15;
|
||||||
|
function operator*<T1, T2, T3> (Self: (T1,T2); v: T3): (T1,T2,T3); extensionmethod;
|
||||||
|
begin
|
||||||
|
Result := (Self[0],Self[1],v);
|
||||||
|
end;
|
||||||
|
|
||||||
|
begin
|
||||||
|
var t0 := (1,2);
|
||||||
|
var t1 := t0 * System.DateTime.Now.DayOfWeek;
|
||||||
|
assert(t1.Item3 = System.DateTime.Now.DayOfWeek);
|
||||||
|
var s := 4+Seq(1,2,3);
|
||||||
|
assert(s.ToArray()[0]=4);
|
||||||
|
end.
|
||||||
31
TestSuite/units/u_extensionmethods4.pas
Normal file
31
TestSuite/units/u_extensionmethods4.pas
Normal file
|
|
@ -0,0 +1,31 @@
|
||||||
|
unit u_extensionmethods4;
|
||||||
|
function string.ToInt2: integer;
|
||||||
|
begin
|
||||||
|
Result := integer.Parse(Self);
|
||||||
|
end;
|
||||||
|
|
||||||
|
function string.ToWords2(params delim: array of char): array of string;
|
||||||
|
begin
|
||||||
|
Result := Self.Split(delim,System.StringSplitOptions.RemoveEmptyEntries);
|
||||||
|
end;
|
||||||
|
|
||||||
|
begin
|
||||||
|
var s := '123';
|
||||||
|
//assert(s.ToInt = 123);
|
||||||
|
var i := s.ToInt2;
|
||||||
|
assert(i=123);
|
||||||
|
s := '222';
|
||||||
|
i := s.ToInt2;
|
||||||
|
assert(i=222);
|
||||||
|
s := '111';
|
||||||
|
i := s.ToInt2();
|
||||||
|
assert(i=111);
|
||||||
|
s := 'abc def';
|
||||||
|
var arr := s.ToWords2;
|
||||||
|
assert(arr[0]='abc');
|
||||||
|
arr := 'ttt xxx'.ToWords2;
|
||||||
|
assert(arr[1] = 'xxx');
|
||||||
|
s := 'p p p';
|
||||||
|
foreach c: string in s.ToWords2 do
|
||||||
|
assert(c = 'p');
|
||||||
|
end.
|
||||||
24
TestSuite/units/u_nested_lambdas_1.pas
Normal file
24
TestSuite/units/u_nested_lambdas_1.pas
Normal file
|
|
@ -0,0 +1,24 @@
|
||||||
|
unit u_nested_lambdas_1;
|
||||||
|
procedure p(f: Func<string, IEnumerable<string>>);
|
||||||
|
begin
|
||||||
|
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure p(f: Func<integer, IEnumerable<integer>>);
|
||||||
|
begin
|
||||||
|
var res := f(3).ToList();
|
||||||
|
assert(res.Count = 4);
|
||||||
|
assert(res[0] = 0);
|
||||||
|
assert(res[1] = 1);
|
||||||
|
assert(res[2] = 4);
|
||||||
|
assert(res[3] = 9);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure Test;
|
||||||
|
begin
|
||||||
|
p(x -> Range(0, x).Select(y -> y * y));
|
||||||
|
end;
|
||||||
|
|
||||||
|
begin
|
||||||
|
Test;
|
||||||
|
end.
|
||||||
3
TestSuite/usesunits/use_extensionmethods15.pas
Normal file
3
TestSuite/usesunits/use_extensionmethods15.pas
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
uses u_extensionmethods15;
|
||||||
|
begin
|
||||||
|
end.
|
||||||
4
TestSuite/usesunits/use_extensionmethods4.pas
Normal file
4
TestSuite/usesunits/use_extensionmethods4.pas
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
uses u_extensionmethods4;
|
||||||
|
begin
|
||||||
|
|
||||||
|
end.
|
||||||
4
TestSuite/usesunits/use_nested_lambdas_1.pas
Normal file
4
TestSuite/usesunits/use_nested_lambdas_1.pas
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
uses u_nested_lambdas_1;
|
||||||
|
begin
|
||||||
|
|
||||||
|
end.
|
||||||
|
|
@ -295,7 +295,9 @@ namespace PascalABCCompiler.NetHelper
|
||||||
private static Dictionary<Type,MethodInfo[]> extension_methods = new Dictionary<Type,MethodInfo[]>();
|
private static Dictionary<Type,MethodInfo[]> extension_methods = new Dictionary<Type,MethodInfo[]>();
|
||||||
private static Dictionary<Type,List<MethodInfo>> type_extensions = new Dictionary<Type, List<MethodInfo>>();
|
private static Dictionary<Type,List<MethodInfo>> type_extensions = new Dictionary<Type, List<MethodInfo>>();
|
||||||
private static Dictionary<Type, Type> arrays_with_extension_methods = new Dictionary<Type, Type>();
|
private static Dictionary<Type, Type> arrays_with_extension_methods = new Dictionary<Type, Type>();
|
||||||
|
private static Dictionary<Type, Type> generics_with_extension_methods = new Dictionary<Type, Type>();
|
||||||
private static Dictionary<int, List<MethodInfo>> generic_array_type_extensions = new Dictionary<int, List<MethodInfo>>();
|
private static Dictionary<int, List<MethodInfo>> generic_array_type_extensions = new Dictionary<int, List<MethodInfo>>();
|
||||||
|
private static List<MethodInfo> generic_parameter_type_extensions = new List<MethodInfo>();
|
||||||
public static Type PABCSystemType = null;
|
public static Type PABCSystemType = null;
|
||||||
public static Type PT4Type = null;
|
public static Type PT4Type = null;
|
||||||
public static Type StringType = typeof(string);
|
public static Type StringType = typeof(string);
|
||||||
|
|
@ -522,6 +524,7 @@ namespace PascalABCCompiler.NetHelper
|
||||||
}
|
}
|
||||||
if (mths2 != null)
|
if (mths2 != null)
|
||||||
mths2.Add(mi);
|
mths2.Add(mi);
|
||||||
|
|
||||||
Dictionary<string, List<MemberInfo>> mht;
|
Dictionary<string, List<MemberInfo>> mht;
|
||||||
if (members.TryGetValue(tmp, out mht))
|
if (members.TryGetValue(tmp, out mht))
|
||||||
{
|
{
|
||||||
|
|
@ -537,6 +540,28 @@ namespace PascalABCCompiler.NetHelper
|
||||||
if (!mis2.Contains(mi))
|
if (!mis2.Contains(mi))
|
||||||
mis2.Add(mi);
|
mis2.Add(mi);
|
||||||
}
|
}
|
||||||
|
if (tmp.IsGenericParameter && !generic_parameter_type_extensions.Contains(mi))
|
||||||
|
{
|
||||||
|
generic_parameter_type_extensions.Add(mi);
|
||||||
|
foreach (Type tt in members.Keys)
|
||||||
|
{
|
||||||
|
if (members.TryGetValue(tt, out mht))
|
||||||
|
{
|
||||||
|
List<MemberInfo> mis2 = null;
|
||||||
|
string name = compiler_string_consts.GetNETOperName(mi.Name);
|
||||||
|
if (name == null)
|
||||||
|
name = mi.Name;
|
||||||
|
if (!mht.TryGetValue(name, out mis2))
|
||||||
|
{
|
||||||
|
mis2 = new List<MemberInfo>();
|
||||||
|
mht.Add(name, mis2);
|
||||||
|
}
|
||||||
|
if (!mis2.Contains(mi))
|
||||||
|
mis2.Add(mi);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
foreach (Type arr_t in arrays_with_extension_methods.Keys)
|
foreach (Type arr_t in arrays_with_extension_methods.Keys)
|
||||||
{
|
{
|
||||||
if (members.TryGetValue(arr_t, out mht))
|
if (members.TryGetValue(arr_t, out mht))
|
||||||
|
|
@ -554,6 +579,24 @@ namespace PascalABCCompiler.NetHelper
|
||||||
mis2.Add(mi);
|
mis2.Add(mi);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
foreach (Type gen_t in generics_with_extension_methods.Keys)
|
||||||
|
{
|
||||||
|
if (members.TryGetValue(gen_t, out mht))
|
||||||
|
{
|
||||||
|
List<MemberInfo> mis2 = null;
|
||||||
|
string name = compiler_string_consts.GetNETOperName(mi.Name);
|
||||||
|
if (name == null)
|
||||||
|
name = mi.Name;
|
||||||
|
if (!mht.TryGetValue(name, out mis2))
|
||||||
|
{
|
||||||
|
mis2 = new List<MemberInfo>();
|
||||||
|
mht.Add(name, mis2);
|
||||||
|
}
|
||||||
|
if (!mis2.Contains(mi))
|
||||||
|
mis2.Add(mi);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
extension_methods.Add(t, ext_meths.ToArray());
|
extension_methods.Add(t, ext_meths.ToArray());
|
||||||
|
|
@ -1077,11 +1120,6 @@ namespace PascalABCCompiler.NetHelper
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//public static void AddMembersOfInterfaceToList(Type t, BindingFlags bf, List<MemberInfo> mem_info)
|
|
||||||
//{
|
|
||||||
//
|
|
||||||
//}
|
|
||||||
|
|
||||||
public static bool IsExtensionMethod(MethodInfo mi)
|
public static bool IsExtensionMethod(MethodInfo mi)
|
||||||
{
|
{
|
||||||
if (ExtensionAttributeType != null && mi.GetCustomAttributes(ExtensionAttributeType, false).Length > 0)
|
if (ExtensionAttributeType != null && mi.GetCustomAttributes(ExtensionAttributeType, false).Length > 0)
|
||||||
|
|
@ -1104,16 +1142,6 @@ namespace PascalABCCompiler.NetHelper
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
//(ssyy) Забираем также и не public члены
|
|
||||||
//(ds) добавил BindingFlags.FlattenHierarchy
|
|
||||||
//(ssyy) убрал BindingFlags.FlattenHierarchy. Зачем оно было нужно? :)
|
|
||||||
//(ds) добавил BindingFlags.FlattenHierarchy, затем что:
|
|
||||||
//Ваня Бондарев (00:52:19 16/12/2007)
|
|
||||||
//BindingFlags.FlattenHierarchy eto flag kotoryj ukazyvaet, chto chleny
|
|
||||||
//tipa nado brat' ne tolko iz samogo tipa, no i ego bazovyh klassov
|
|
||||||
//t.GetMembers(BindingFlags.FlattenHierarchy) naprimer. Dlja vybora staticheskih
|
|
||||||
//chlenov eto objazatelno.
|
|
||||||
//Без этого не работает пример
|
|
||||||
BindingFlags bf = BindingFlags.FlattenHierarchy | BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic;
|
BindingFlags bf = BindingFlags.FlattenHierarchy | BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic;
|
||||||
MemberInfo[] mis;
|
MemberInfo[] mis;
|
||||||
if (t.IsInterface)
|
if (t.IsInterface)
|
||||||
|
|
@ -1146,20 +1174,36 @@ namespace PascalABCCompiler.NetHelper
|
||||||
{
|
{
|
||||||
ht[mi.Name].Add(mi);
|
ht[mi.Name].Add(mi);
|
||||||
}
|
}
|
||||||
if (ExtensionAttributeType != null /*&& t != StringType*/ && cur_used_assemblies.ContainsKey(SystemCoreAssembly))
|
if (ExtensionAttributeType != null)
|
||||||
{
|
{
|
||||||
List<MethodInfo> meths = null;
|
List<MethodInfo> meths = null;
|
||||||
Type tmp_t = t;
|
Type tmp_t = t;
|
||||||
if (tmp_t.IsArray)
|
if (tmp_t.IsArray)
|
||||||
arrays_with_extension_methods[tmp_t] = tmp_t;
|
arrays_with_extension_methods[tmp_t] = tmp_t;
|
||||||
|
if (tmp_t.IsGenericTypeDefinition)
|
||||||
|
generics_with_extension_methods[tmp_t] = tmp_t;
|
||||||
cached_type_extensions[t] = t;
|
cached_type_extensions[t] = t;
|
||||||
while (tmp_t != null)
|
while (tmp_t != null)
|
||||||
{
|
{
|
||||||
if (type_extensions.TryGetValue(tmp_t, out meths)
|
List<MethodInfo> meths1 = null;
|
||||||
|| tmp_t.IsGenericType && type_extensions.TryGetValue(tmp_t.GetGenericTypeDefinition(), out meths)
|
List<MethodInfo> meths2 = null;
|
||||||
|| tmp_t.IsArray && generic_array_type_extensions.TryGetValue(tmp_t.GetArrayRank(), out meths))
|
List<MethodInfo> meths3 = generic_parameter_type_extensions;
|
||||||
|
if (tmp_t.IsGenericType && !tmp_t.IsGenericTypeDefinition)
|
||||||
|
type_extensions.TryGetValue(tmp_t.GetGenericTypeDefinition(), out meths1);
|
||||||
|
if (tmp_t.IsArray)
|
||||||
|
generic_array_type_extensions.TryGetValue(tmp_t.GetArrayRank(), out meths2);
|
||||||
|
if (type_extensions.TryGetValue(tmp_t, out meths) || meths1 != null || meths2 != null || meths3 != null)
|
||||||
{
|
{
|
||||||
foreach (MethodInfo mi in meths)
|
List<MethodInfo> all_meths = new List<MethodInfo>();
|
||||||
|
if (meths != null)
|
||||||
|
all_meths.AddRange(meths);
|
||||||
|
if (meths1 != null)
|
||||||
|
all_meths.AddRange(meths1);
|
||||||
|
if (meths2 != null)
|
||||||
|
all_meths.AddRange(meths2);
|
||||||
|
if (meths3 != null)
|
||||||
|
all_meths.AddRange(meths3);
|
||||||
|
foreach (MethodInfo mi in all_meths)
|
||||||
{
|
{
|
||||||
if (cur_used_assemblies.ContainsKey(mi.DeclaringType.Assembly))
|
if (cur_used_assemblies.ContainsKey(mi.DeclaringType.Assembly))
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -1997,61 +1997,6 @@ namespace PascalABCCompiler.TreeConverter
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Исправить этот алгоритм, сделав каждый с каждым - вроде исправил - см. выше
|
|
||||||
/*j = 1;
|
|
||||||
while(j<set_of_possible_functions.Count)
|
|
||||||
{
|
|
||||||
method_compare mc = compare_methods(set_of_possible_functions[0],
|
|
||||||
set_of_possible_functions[j], tcll[0], tcll[j]);
|
|
||||||
if (mc==method_compare.greater_method)
|
|
||||||
{
|
|
||||||
tcll.remove_at(j);
|
|
||||||
set_of_possible_functions.remove_at(j);
|
|
||||||
remove=true;
|
|
||||||
}
|
|
||||||
else if (mc==method_compare.less_method)
|
|
||||||
{
|
|
||||||
tcll[0]=tcll[j];
|
|
||||||
set_of_possible_functions[0]=set_of_possible_functions[j];
|
|
||||||
tcll.remove_at(j);
|
|
||||||
set_of_possible_functions.remove_at(j);
|
|
||||||
remove=true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
j++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
|
|
||||||
/*remove=true;
|
|
||||||
while (remove)
|
|
||||||
{
|
|
||||||
if (set_of_possible_functions.Count == 1)
|
|
||||||
{
|
|
||||||
check_single_possible_convertion(loc, tcll[0]);
|
|
||||||
convert_function_call_expressions(set_of_possible_functions[0], parameters, tcll[0]);
|
|
||||||
return set_of_possible_functions[0];
|
|
||||||
}
|
|
||||||
remove = false;
|
|
||||||
j = 1;
|
|
||||||
while (j < set_of_possible_functions.Count)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
//Тут некоторое дублирование кода, но сюда программа не должна никогда зайти.
|
|
||||||
//Должен быть выполнен if выше.
|
|
||||||
//Но пусть пока повисит. Потом нужно разобраться и убрать.
|
|
||||||
/*if (set_of_possible_functions.Count==1)
|
|
||||||
{
|
|
||||||
check_single_possible_conversion(func_call,tcll[0]);
|
|
||||||
func_call.function=set_of_possible_functions[0];
|
|
||||||
convert_function_call_expressions(func_call,tcll[0]);
|
|
||||||
func_call.type=func_call.function.return_value_type;
|
|
||||||
return func_call;
|
|
||||||
}*/
|
|
||||||
|
|
||||||
//Тупая заглушка для примитивных типов. иначе не работает +=, у нас лишком много неявных приведений
|
//Тупая заглушка для примитивных типов. иначе не работает +=, у нас лишком много неявных приведений
|
||||||
//в дальнейшем может вызвать странное поведение, это надо проверить
|
//в дальнейшем может вызвать странное поведение, это надо проверить
|
||||||
if (set_of_possible_functions.Count == 2 && indefinits.Count == 0)
|
if (set_of_possible_functions.Count == 2 && indefinits.Count == 0)
|
||||||
|
|
@ -2083,9 +2028,59 @@ namespace PascalABCCompiler.TreeConverter
|
||||||
return new indefinite_functions_set(indefinits);
|
return new indefinite_functions_set(indefinits);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SortedDictionary<int, List<function_node>> distances = new SortedDictionary<int, List<function_node>>();
|
||||||
|
foreach (function_node fn in set_of_possible_functions)
|
||||||
|
{
|
||||||
|
int distance = 0;
|
||||||
|
for (int i = 0; i < parameters.Count; i++)
|
||||||
|
{
|
||||||
|
type_node from = parameters[i].type;
|
||||||
|
type_node to = fn.parameters[Math.Min(i,fn.parameters.Count-1)].type;
|
||||||
|
if (fn.parameters[Math.Min(i, fn.parameters.Count - 1)].is_params)
|
||||||
|
to = to.element_type;
|
||||||
|
distance += get_type_distance(from, to);
|
||||||
|
}
|
||||||
|
List<function_node> lst;
|
||||||
|
if (distances.TryGetValue(distance,out lst))
|
||||||
|
{
|
||||||
|
lst.Add(fn);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
lst = new List<function_node>();
|
||||||
|
lst.Add(fn);
|
||||||
|
distances[distance] = lst;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
foreach (int dist in distances.Keys)
|
||||||
|
{
|
||||||
|
List<function_node> funcs = distances[dist];
|
||||||
|
if (funcs.Count == 1)
|
||||||
|
{
|
||||||
|
possible_type_convertions_list tcl = get_conversions(parameters, funcs[0].parameters, true, loc);
|
||||||
|
convert_function_call_expressions(funcs[0], parameters, tcl);
|
||||||
|
return funcs[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
return AddError<function_node>(new SeveralFunctionsCanBeCalled(loc,set_of_possible_functions));
|
return AddError<function_node>(new SeveralFunctionsCanBeCalled(loc,set_of_possible_functions));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private int get_type_distance(type_node from, type_node to)
|
||||||
|
{
|
||||||
|
if (from == to)
|
||||||
|
return 0;
|
||||||
|
type_compare tc = type_table.compare_types(from, to);
|
||||||
|
if (tc == type_compare.non_comparable_type)
|
||||||
|
return 1000;
|
||||||
|
if (!from.IsInterface && to.IsInterface)
|
||||||
|
return 2;
|
||||||
|
if (tc == type_compare.less_type)
|
||||||
|
return 1;
|
||||||
|
if (tc == type_compare.greater_type)
|
||||||
|
return 3;
|
||||||
|
return 1000;
|
||||||
|
}
|
||||||
|
|
||||||
private function_node is_exist_eq_return_value_method(function_node fn, function_node_list funcs)
|
private function_node is_exist_eq_return_value_method(function_node fn, function_node_list funcs)
|
||||||
{
|
{
|
||||||
fn = find_eq_return_value_method_in_list(fn, funcs);
|
fn = find_eq_return_value_method_in_list(fn, funcs);
|
||||||
|
|
|
||||||
|
|
@ -12170,6 +12170,8 @@ namespace PascalABCCompiler.TreeConverter
|
||||||
top_function.ConnectedToType.base_type.Scope.AddSymbol(top_function.name, new SymbolInfo(context.top_function));
|
top_function.ConnectedToType.base_type.Scope.AddSymbol(top_function.name, new SymbolInfo(context.top_function));
|
||||||
else if (top_function.ConnectedToType.is_generic_parameter)
|
else if (top_function.ConnectedToType.is_generic_parameter)
|
||||||
top_function.ConnectedToType.base_type.Scope.AddSymbol(top_function.name, new SymbolInfo(context.top_function));
|
top_function.ConnectedToType.base_type.Scope.AddSymbol(top_function.name, new SymbolInfo(context.top_function));
|
||||||
|
else if (top_function.ConnectedToType is compiled_generic_instance_type_node && top_function.ConnectedToType.original_generic.Scope != null)
|
||||||
|
top_function.ConnectedToType.original_generic.Scope.AddSymbol(top_function.name, new SymbolInfo(context.top_function));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
|
|
||||||
|
|
@ -3108,7 +3108,7 @@ namespace PascalABCCompiler.TreeRealization
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private SymbolInfo AddToSymbolInfo(SymbolInfo to, SymbolInfo from)
|
private SymbolInfo AddToSymbolInfo(SymbolInfo to, SymbolInfo from, bool clone=false)
|
||||||
{
|
{
|
||||||
if (to==null)
|
if (to==null)
|
||||||
{
|
{
|
||||||
|
|
@ -3117,6 +3117,16 @@ namespace PascalABCCompiler.TreeRealization
|
||||||
if (from == null)
|
if (from == null)
|
||||||
{
|
{
|
||||||
return to;
|
return to;
|
||||||
|
}
|
||||||
|
if (clone)
|
||||||
|
{
|
||||||
|
SymbolInfo old = to;
|
||||||
|
to = new SymbolInfo();
|
||||||
|
to.sym_info = old.sym_info;
|
||||||
|
to.Next = old.Next;
|
||||||
|
to.scope = old.scope;
|
||||||
|
to.symbol_kind = old.symbol_kind;
|
||||||
|
to.access_level = old.access_level;
|
||||||
}
|
}
|
||||||
SymbolInfo iter=to;
|
SymbolInfo iter=to;
|
||||||
while(iter.Next!=null)
|
while(iter.Next!=null)
|
||||||
|
|
@ -3175,13 +3185,74 @@ namespace PascalABCCompiler.TreeRealization
|
||||||
SymbolInfo si = scope.SymbolTable.Find(scope, name);
|
SymbolInfo si = scope.SymbolTable.Find(scope, name);
|
||||||
SymbolInfo si2 = find_in_additional_names(name);
|
SymbolInfo si2 = find_in_additional_names(name);
|
||||||
SymbolInfo si3 = compiled_find(name);
|
SymbolInfo si3 = compiled_find(name);
|
||||||
|
bool clone = false;
|
||||||
if (this.type_special_kind == SemanticTree.type_special_kind.array_kind && this.base_type.Scope != null)
|
if (this.type_special_kind == SemanticTree.type_special_kind.array_kind && this.base_type.Scope != null)
|
||||||
{
|
{
|
||||||
SymbolInfo tmp_si = this.base_type.Scope.SymbolTable.Find(this.base_type.Scope, name);
|
SymbolInfo tmp_si = this.base_type.Scope.SymbolTable.Find(this.base_type.Scope, name);
|
||||||
if (tmp_si != null)
|
if (tmp_si != null)
|
||||||
{
|
{
|
||||||
tmp_si.Next = si;
|
if (si == null)
|
||||||
si = tmp_si;
|
si = tmp_si;
|
||||||
|
else if (si.sym_info != tmp_si.sym_info)
|
||||||
|
{
|
||||||
|
tmp_si.Next = si;
|
||||||
|
si = tmp_si;
|
||||||
|
}
|
||||||
|
clone = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (this.compiled_type.IsGenericType && !this.compiled_type.IsGenericTypeDefinition)
|
||||||
|
{
|
||||||
|
compiled_type_node ctn = compiled_type_node.get_type_node(this.compiled_type.GetGenericTypeDefinition());
|
||||||
|
if (ctn.scope != null)
|
||||||
|
{
|
||||||
|
SymbolInfo tmp_si = ctn.scope.SymbolTable.Find(ctn.scope, name);
|
||||||
|
if (tmp_si != null && tmp_si.sym_info is function_node && (tmp_si.sym_info as function_node).is_extension_method)
|
||||||
|
{
|
||||||
|
if (si == null)
|
||||||
|
si = tmp_si;
|
||||||
|
else if (si.sym_info != tmp_si.sym_info)
|
||||||
|
si = AddToSymbolInfo(si, tmp_si);
|
||||||
|
clone = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
compiled_type_node bas_type = base_type as compiled_type_node;
|
||||||
|
while (bas_type != null && bas_type.scope != null)
|
||||||
|
{
|
||||||
|
SymbolInfo tmp_si = bas_type.scope.SymbolTable.Find(bas_type.scope, name);
|
||||||
|
if (tmp_si != null && tmp_si.sym_info is function_node && (tmp_si.sym_info as function_node).is_extension_method)
|
||||||
|
{
|
||||||
|
if (si == null)
|
||||||
|
si = tmp_si;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (si.sym_info != tmp_si.sym_info)
|
||||||
|
si = AddToSymbolInfo(si, tmp_si);
|
||||||
|
}
|
||||||
|
clone = true;
|
||||||
|
}
|
||||||
|
bas_type = bas_type.base_type as compiled_type_node;
|
||||||
|
}
|
||||||
|
for (int i = 0; i < ImplementingInterfaces.Count; i++)
|
||||||
|
{
|
||||||
|
compiled_type_node ctn = ImplementingInterfaces[i] as compiled_type_node;
|
||||||
|
if (ctn.is_generic_type_instance)
|
||||||
|
ctn = ctn.original_generic as compiled_type_node;
|
||||||
|
if (ctn != null && ctn.scope != null)
|
||||||
|
{
|
||||||
|
SymbolInfo tmp_si = ctn.scope.SymbolTable.Find(ctn.scope, name);
|
||||||
|
if (tmp_si != null && tmp_si.sym_info is function_node && (tmp_si.sym_info as function_node).is_extension_method)
|
||||||
|
{
|
||||||
|
if (si == null)
|
||||||
|
si = tmp_si;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (si.sym_info != tmp_si.sym_info)
|
||||||
|
si = AddToSymbolInfo(si, tmp_si);
|
||||||
|
}
|
||||||
|
clone = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (si != null)
|
if (si != null)
|
||||||
|
|
@ -3193,33 +3264,12 @@ namespace PascalABCCompiler.TreeRealization
|
||||||
}
|
}
|
||||||
else if (si3 != null)
|
else if (si3 != null)
|
||||||
si = si3;
|
si = si3;
|
||||||
if (si == null && si2 == null && string.Compare(name, "Create", true) != 0)
|
|
||||||
{
|
|
||||||
compiled_type_node bas_type = base_type as compiled_type_node;
|
|
||||||
while (si == null && bas_type != null && bas_type.scope != null)
|
|
||||||
{
|
|
||||||
si = bas_type.scope.SymbolTable.Find(bas_type.scope, name);
|
|
||||||
bas_type = bas_type.base_type as compiled_type_node;
|
|
||||||
}
|
|
||||||
if (si == null)
|
|
||||||
{
|
|
||||||
for (int i = 0; i < ImplementingInterfaces.Count; i++)
|
|
||||||
{
|
|
||||||
compiled_type_node ctn = ImplementingInterfaces[i] as compiled_type_node;
|
|
||||||
if (ctn.is_generic_type_instance)
|
|
||||||
ctn = ctn.original_generic as compiled_type_node;
|
|
||||||
if (ctn != null && ctn.scope != null)
|
|
||||||
si = ctn.scope.SymbolTable.Find(ctn.scope, name);
|
|
||||||
if (si != null)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (si == null && si2 == null && this == SystemLibrary.SystemLibrary.string_type && SystemLibrary.SystemLibrary.syn_visitor.from_pabc_dll)
|
if (si == null && si2 == null && this == SystemLibrary.SystemLibrary.string_type && SystemLibrary.SystemLibrary.syn_visitor.from_pabc_dll)
|
||||||
{
|
{
|
||||||
si = compiled_type_node.get_type_node(NetHelper.NetHelper.PABCSystemType).find_in_type(name);
|
si = compiled_type_node.get_type_node(NetHelper.NetHelper.PABCSystemType).find_in_type(name);
|
||||||
}
|
}
|
||||||
return AddToSymbolInfo(si, si2);
|
return AddToSymbolInfo(si, si2, clone);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue