extensionmethod in units

bug fix: unary operator + caused the internal error
new tests in test suite
This commit is contained in:
Бондарев Иван 2015-10-24 20:18:49 +02:00
parent 78ba53dea9
commit e269115ff1
15 changed files with 7950 additions and 26 deletions

View file

@ -6,6 +6,6 @@ namespace PascalABCCompiler.PCU
{ {
public static class PCUFileFormatVersion public static class PCUFileFormatVersion
{ {
public static System.Int16 Version = 104; public static System.Int16 Version = 105;
} }
} }

View file

@ -269,11 +269,12 @@ namespace PascalABCCompiler.PCU
} }
cur_doc = new document(SourceFileName); cur_doc = new document(SourceFileName);
AddNamespaces();
AddInterfaceNames(); AddInterfaceNames();
//ssyy //ssyy
AddImplementationNames(); AddImplementationNames();
//\ssyy //\ssyy
AddNamespaces();
//AddInitFinalMethods(); //AddInitFinalMethods();
//ProcessWaitedToRestoreFields(); //ProcessWaitedToRestoreFields();
unit.State = UnitState.Compiled; unit.State = UnitState.Compiled;
@ -475,7 +476,9 @@ namespace PascalABCCompiler.PCU
type_node tn = GetSpecialTypeRefernce(names[i].offset); type_node tn = GetSpecialTypeRefernce(names[i].offset);
if (tn is compiled_type_node) if (tn is compiled_type_node)
(tn as compiled_type_node).scope.AddSymbol(names[i].name,si); (tn as compiled_type_node).scope.AddSymbol(names[i].name, si);
else if (tn is generic_instance_type_node)
tn.Scope.AddSymbol(names[i].name, si);
else if (tn is common_type_node) else if (tn is common_type_node)
(tn as common_type_node).scope.AddSymbol(names[i].name, si); (tn as common_type_node).scope.AddSymbol(names[i].name, si);
else else
@ -2696,6 +2699,7 @@ namespace PascalABCCompiler.PCU
AddMember(cnfn, offset); AddMember(cnfn, offset);
type_node ConnectedToType = null; type_node ConnectedToType = null;
br.ReadInt32();
if (CanReadObject()) if (CanReadObject())
ConnectedToType = GetTypeReference(); ConnectedToType = GetTypeReference();
br.ReadBoolean();//пропускаем флаг - интерфейсности br.ReadBoolean();//пропускаем флаг - интерфейсности
@ -2758,6 +2762,7 @@ namespace PascalABCCompiler.PCU
int pos = (int)br.BaseStream.Position; int pos = (int)br.BaseStream.Position;
br.BaseStream.Seek(start_pos + offset, SeekOrigin.Begin); br.BaseStream.Seek(start_pos + offset, SeekOrigin.Begin);
br.ReadByte(); br.ReadByte();
br.ReadInt32();
type_node tn = null; type_node tn = null;
if (CanReadObject()) if (CanReadObject())
tn = GetTypeReference(); tn = GetTypeReference();
@ -2771,13 +2776,17 @@ namespace PascalABCCompiler.PCU
if (members.TryGetValue(offset, out dn)) if (members.TryGetValue(offset, out dn))
return dn as common_namespace_function_node; return dn as common_namespace_function_node;
common_namespace_function_node cnfn = null; common_namespace_function_node cnfn = null;
int pos = (int)br.BaseStream.Position;
int pos = (int)br.BaseStream.Position;
br.BaseStream.Seek(start_pos+offset,SeekOrigin.Begin); br.BaseStream.Seek(start_pos+offset,SeekOrigin.Begin);
br.ReadByte(); br.ReadByte();
int func_pos = start_pos + br.ReadInt32();
int connected_to_type_pos = (int)br.BaseStream.Position;
br.BaseStream.Seek(func_pos, SeekOrigin.Begin);
string name; string name;
type_node ConnectedToType = null; type_node ConnectedToType = null;
if (CanReadObject()) /*if (CanReadObject())
ConnectedToType = GetTypeReference(); ConnectedToType = GetTypeReference();*/
bool is_interface = br.ReadBoolean(); bool is_interface = br.ReadBoolean();
if (is_interface)//пропускаем флаг - интерфейсности if (is_interface)//пропускаем флаг - интерфейсности
{ {
@ -2789,16 +2798,21 @@ namespace PascalABCCompiler.PCU
} }
if (is_interface) if (is_interface)
{ {
cnfn = new common_namespace_function_node(name,null,cun.namespaces[0],null); cnfn = new common_namespace_function_node(name,null,cun.namespaces[0],null);
int_members.Add(cnfn); int_members.Add(cnfn);
} }
else else
{ {
cnfn = new common_namespace_function_node(name,null,cun.namespaces[1],null); cnfn = new common_namespace_function_node(name,null,cun.namespaces[1],null);
impl_members.Add(cnfn); impl_members.Add(cnfn);
} }
ReadGenericFunctionInformation(cnfn); ReadGenericFunctionInformation(cnfn);
AddMember(cnfn, offset); AddMember(cnfn, offset);
int cur_pos = (int)br.BaseStream.Position;
br.BaseStream.Seek(connected_to_type_pos, SeekOrigin.Begin);
if (CanReadObject())
ConnectedToType = GetTypeReference();
br.BaseStream.Seek(cur_pos, SeekOrigin.Begin);
if (br.ReadByte() == 1) if (br.ReadByte() == 1)
{ {
cnfn.return_value_type = GetTypeReference(); cnfn.return_value_type = GetTypeReference();

View file

@ -2915,9 +2915,14 @@ namespace PascalABCCompiler.PCU
FinalizationMethodOffset = pos; FinalizationMethodOffset = pos;
bw.Write((byte)func.semantic_node_type); bw.Write((byte)func.semantic_node_type);
int connected_to_type_pos = (int)bw.BaseStream.Position;
bw.Write(0);
if (CanWriteObject(func.ConnectedToType)) if (CanWriteObject(func.ConnectedToType))
WriteTypeReference(func.ConnectedToType); WriteTypeReference(func.ConnectedToType);
int cur_pos = (int)bw.BaseStream.Position;
bw.Seek(connected_to_type_pos, SeekOrigin.Begin);
bw.Write(cur_pos);
bw.Seek(cur_pos, SeekOrigin.Begin);
bw.Write(is_interface); bw.Write(is_interface);
if (is_interface == true) if (is_interface == true)
bw.Write(GetNameIndex(func)); bw.Write(GetNameIndex(func));

View file

@ -6903,7 +6903,7 @@ namespace PascalABCCompiler.NETGenerator
if (tmp_dot == true) if (tmp_dot == true)
{ {
//MethodInfo mi = value.static_method.method_info; //MethodInfo mi = value.static_method.method_info;
if (mi.ReturnType.IsValueType && !NETGeneratorTools.IsPointer(mi.ReturnType)) if ((mi.ReturnType.IsValueType || mi.ReturnType.IsGenericParameter) && !NETGeneratorTools.IsPointer(mi.ReturnType))
{ {
LocalBuilder lb = il.DeclareLocal(mi.ReturnType); LocalBuilder lb = il.DeclareLocal(mi.ReturnType);
il.Emit(OpCodes.Stloc, lb); il.Emit(OpCodes.Stloc, lb);
@ -7162,7 +7162,7 @@ namespace PascalABCCompiler.NETGenerator
{ {
//if (mi.ReturnType.IsValueType && !NETGeneratorTools.IsPointer(mi.ReturnType)) //if (mi.ReturnType.IsValueType && !NETGeneratorTools.IsPointer(mi.ReturnType))
//Для правильной работы шаблонов поменял условие (ssyy, 15.05.2009) //Для правильной работы шаблонов поменял условие (ssyy, 15.05.2009)
if ((value.method.return_value_type != null && value.method.return_value_type.is_value_type || value.method.return_value_type.is_generic_parameter) && !NETGeneratorTools.IsPointer(mi.ReturnType)) if ((value.method.return_value_type != null && value.method.return_value_type.is_value_type /*|| value.method.return_value_type != null && value.method.return_value_type.is_generic_parameter*/) && !NETGeneratorTools.IsPointer(mi.ReturnType))
{ {
LocalBuilder lb = mi.ReturnType.IsGenericParameter ? LocalBuilder lb = mi.ReturnType.IsGenericParameter ?
il.DeclareLocal(helper.GetTypeReference(value.method.return_value_type).tp) : il.DeclareLocal(helper.GetTypeReference(value.method.return_value_type).tp) :

View file

@ -841,15 +841,15 @@ end;
OperatorServices = class OperatorServices = class
// Methods // Methods
public constructor Create; public constructor Create;
public function IsAssigmentOperator(&Operator: Operators): boolean; static; public class function IsAssigmentOperator(&Operator: Operators): boolean;
public function ToString(&Operator: Operators; Language: LanguageId): string; static; public class function ToString(&Operator: Operators; Language: LanguageId): string;
end; end;
Utils = class Utils = class
// Methods // Methods
public constructor Create; public constructor Create;
public function IdentListToString(list: List<ident>; separator: string): string; static; public class function IdentListToString(list: List<ident>; separator: string): string;
end; end;
@ -6839,12 +6839,12 @@ begin
end; end;
function OperatorServices.IsAssigmentOperator(&Operator: Operators): boolean; class function OperatorServices.IsAssigmentOperator(&Operator: Operators): boolean;
begin begin
end; end;
function OperatorServices.ToString(&Operator: Operators; Language: LanguageId): string; class function OperatorServices.ToString(&Operator: Operators; Language: LanguageId): string;
begin begin
end; end;
@ -6855,7 +6855,7 @@ begin
end; end;
function Utils.IdentListToString(list: List<ident>; separator: string): string; class function Utils.IdentListToString(list: List<ident>; separator: string): string;
begin begin
end; end;

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,10 @@
uses extensionmethods10u;
procedure Test(x: integer);
begin
assert(x=3);
end;
begin
var a := Seq(3,3,3);
a.MyForeach(Test);
end.

View file

@ -0,0 +1,7 @@
unit extensionmethods10u;
procedure MyForEach<T>(self: sequence of T; action: T -> ()); extensionmethod;
begin
foreach x: T in Self do
action(x);
end;
end.

View file

@ -3,6 +3,7 @@ type
procedure Add(a: T); procedure Add(a: T);
begin begin
assert(a.Equals(5)); assert(a.Equals(5));
assert(a.ToString()='5');
end; end;
procedure Add2(a:T);virtual; procedure Add2(a:T);virtual;

14
TestSuite/generics5.pas Normal file
View file

@ -0,0 +1,14 @@
procedure System.Collections.Generic.IEnumerable<TSource>.Show;
begin
var qq := self.ElementAt(0).ToString();
assert(qq = '2');
{var obj := object(self.ElementAt(0));
assert(obj.ToString()='2');
assert(object(self.ElementAt(0)).ToString()='2');}
var t: TSource;
assert(t.ToString() = '0');
end;
begin
var a := Arr(2,3,4);
a.Show;
end.

25
TestSuite/generics6.pas Normal file
View file

@ -0,0 +1,25 @@
type
Slc<T> = class
l: List<T>;
constructor (l: List<T>);
begin
self.l := l;
end;
public
procedure p;
begin
assert(l[0].ToString()='666');
var t := l[0];
assert(t.ToString='666');
var arr := Arr(l[0]);
assert(arr[0].ToString()='666');
//assert(object(l[0]).ToString()='666');
end;
end;
begin
var l := new List<integer>();
l.Add(666);
var s := new Slc<integer>(l);
s.p;
end.

View file

@ -849,6 +849,8 @@ namespace PascalABCCompiler.TreeConverter
{ {
vdn = syntax_tree_visitor.context.add_var_definition(get_temp_arr_name(), loc); vdn = syntax_tree_visitor.context.add_var_definition(get_temp_arr_name(), loc);
} }
else if (syntax_tree_visitor.context.converted_type != null)
vdn = syntax_tree_visitor.context.add_field(get_temp_arr_name(), loc, pr.type, polymorphic_state.ps_static);
else else
vdn = syntax_tree_visitor.context.add_var_definition_in_entry_scope(get_temp_arr_name(), loc); vdn = syntax_tree_visitor.context.add_var_definition_in_entry_scope(get_temp_arr_name(), loc);

View file

@ -1020,7 +1020,7 @@ namespace PascalABCCompiler.TreeConverter
} }
//#endif //#endif
SymbolInfo si = expr.type.find(name, context.CurrentScope); SymbolInfo si = expr.type.find(name, context.CurrentScope);
if (si == null) if (si == null || si.sym_info is wrapped_definition_node)
{ {
AddError(new OperatorCanNotBeAppliedToThisType(name, expr)); AddError(new OperatorCanNotBeAppliedToThisType(name, expr));
} }

View file

@ -593,15 +593,15 @@ namespace PascalABCCompiler.TreeRealization
[Serializable] [Serializable]
public abstract class common_function_node : function_node, SemanticTree.ICommonFunctionNode public abstract class common_function_node : function_node, SemanticTree.ICommonFunctionNode
{ {
private string _name; protected string _name;
private readonly local_variable_list _var_defs = new local_variable_list(); protected readonly local_variable_list _var_defs = new local_variable_list();
private readonly List<label_node> _label_defs = new List<label_node>(); protected readonly List<label_node> _label_defs = new List<label_node>();
private readonly function_constant_definition_list _const_defs = new function_constant_definition_list(); protected readonly function_constant_definition_list _const_defs = new function_constant_definition_list();
private SemanticTree.SpecialFunctionKind specialFunctionKind = SemanticTree.SpecialFunctionKind.None; protected SemanticTree.SpecialFunctionKind specialFunctionKind = SemanticTree.SpecialFunctionKind.None;
public SemanticTree.SpecialFunctionKind SpecialFunctionKind public SemanticTree.SpecialFunctionKind SpecialFunctionKind
{ {
@ -1097,6 +1097,10 @@ namespace PascalABCCompiler.TreeRealization
{ {
return _namespace; return _namespace;
} }
set
{
_namespace = value;
}
} }
/// <summary> /// <summary>

View file

@ -407,6 +407,8 @@ namespace PascalABCCompiler.TreeRealization
public static bool is_derived(type_node base_class,type_node derived_class) public static bool is_derived(type_node base_class,type_node derived_class)
{ {
if (derived_class == null) //void? if (derived_class == null) //void?
return false;
if (base_class == null)
return false; return false;
type_node tn=derived_class.base_type; type_node tn=derived_class.base_type;
//TODO: Проверить на ссылочный и размерный тип. //TODO: Проверить на ссылочный и размерный тип.