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 System.Int16 Version = 104;
public static System.Int16 Version = 105;
}
}

View file

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

View file

@ -2915,9 +2915,14 @@ namespace PascalABCCompiler.PCU
FinalizationMethodOffset = pos;
bw.Write((byte)func.semantic_node_type);
int connected_to_type_pos = (int)bw.BaseStream.Position;
bw.Write(0);
if (CanWriteObject(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);
if (is_interface == true)
bw.Write(GetNameIndex(func));

View file

@ -6903,7 +6903,7 @@ namespace PascalABCCompiler.NETGenerator
if (tmp_dot == true)
{
//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);
il.Emit(OpCodes.Stloc, lb);
@ -7162,7 +7162,7 @@ namespace PascalABCCompiler.NETGenerator
{
//if (mi.ReturnType.IsValueType && !NETGeneratorTools.IsPointer(mi.ReturnType))
//Для правильной работы шаблонов поменял условие (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 ?
il.DeclareLocal(helper.GetTypeReference(value.method.return_value_type).tp) :

View file

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

View file

@ -593,15 +593,15 @@ namespace PascalABCCompiler.TreeRealization
[Serializable]
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
{
@ -638,7 +638,7 @@ namespace PascalABCCompiler.TreeRealization
get { return _generic_params; }
set { _generic_params = value; }
}
public override List<type_node> get_generic_params_list()
{
if (_generic_params == null)
@ -1097,6 +1097,10 @@ namespace PascalABCCompiler.TreeRealization
{
return _namespace;
}
set
{
_namespace = value;
}
}
/// <summary>

View file

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