This commit is contained in:
Бондарев Иван 2017-07-06 20:33:38 +02:00
parent b3022fff00
commit 485d6b4445
3 changed files with 48 additions and 19 deletions

View file

@ -5085,7 +5085,7 @@ namespace PascalABCCompiler.NETGenerator
public override void visit(SemanticTree.IStaticCompiledFieldReferenceNode value) public override void visit(SemanticTree.IStaticCompiledFieldReferenceNode value)
{ {
//если у поля нет постоянное значение //если у поля нет постоянное значение
if (value.static_field.compiled_field.IsLiteral == false) if (!value.static_field.compiled_field.IsLiteral)
{ {
if (is_addr == false) if (is_addr == false)
{ {
@ -5102,7 +5102,7 @@ namespace PascalABCCompiler.NETGenerator
{ {
//иначе кладем константу //иначе кладем константу
NETGeneratorTools.PushLdc(il, value.static_field.compiled_field.FieldType, value.static_field.compiled_field.GetRawConstantValue()); NETGeneratorTools.PushLdc(il, value.static_field.compiled_field.FieldType, value.static_field.compiled_field.GetRawConstantValue());
if (is_dot_expr == true) if (is_dot_expr)
{ {
//нужно упаковать //нужно упаковать
il.Emit(OpCodes.Box, value.static_field.compiled_field.FieldType); il.Emit(OpCodes.Box, value.static_field.compiled_field.FieldType);
@ -5132,7 +5132,7 @@ namespace PascalABCCompiler.NETGenerator
else else
{ {
NETGeneratorTools.PushLdc(il, value.field.compiled_field.FieldType, value.field.compiled_field.GetRawConstantValue()); NETGeneratorTools.PushLdc(il, value.field.compiled_field.FieldType, value.field.compiled_field.GetRawConstantValue());
if (tmp_dot == true) if (tmp_dot)
{ {
il.Emit(OpCodes.Box, value.field.compiled_field.FieldType); il.Emit(OpCodes.Box, value.field.compiled_field.FieldType);
} }
@ -5164,13 +5164,6 @@ namespace PascalABCCompiler.NETGenerator
} }
else else
il.Emit(OpCodes.Ldsflda, fi); il.Emit(OpCodes.Ldsflda, fi);
/*if (is_dot_expr)
{
//здесь в условии ошибка
//(ssyy) интересно, какая:) Добавил проверку для generics
if (fi.FieldType.IsValueType && fi.FieldType.IsPrimitive || fi.FieldType.IsGenericParameter)
il.Emit(OpCodes.Box, fi.FieldType);
}*/
} }
public override void visit(SemanticTree.ICommonClassFieldReferenceNode value) public override void visit(SemanticTree.ICommonClassFieldReferenceNode value)
@ -5247,9 +5240,9 @@ namespace PascalABCCompiler.NETGenerator
if (vi.kind == VarKind.vkLocal)//если локальная if (vi.kind == VarKind.vkLocal)//если локальная
{ {
LocalBuilder lb = vi.lb; LocalBuilder lb = vi.lb;
if (is_addr == false)//если это факт. var-параметр if (!is_addr)//если это факт. var-параметр
{ {
if (is_dot_expr == true) //если после перем. в выражении стоит точка if (is_dot_expr) //если после перем. в выражении стоит точка
{ {
if (lb.LocalType.IsGenericParameter) if (lb.LocalType.IsGenericParameter)
{ {
@ -5257,7 +5250,7 @@ namespace PascalABCCompiler.NETGenerator
il.Emit(OpCodes.Box, lb.LocalType); il.Emit(OpCodes.Box, lb.LocalType);
} }
else else
if (lb.LocalType.IsValueType == true) if (lb.LocalType.IsValueType)
{ {
il.Emit(OpCodes.Ldloca, lb);//если перем. размерного типа кладем ее адрес il.Emit(OpCodes.Ldloca, lb);//если перем. размерного типа кладем ее адрес
} }
@ -6635,8 +6628,11 @@ namespace PascalABCCompiler.NETGenerator
//ICompiledTypeNode ctn = value.real_parameters[i].type as ICompiledTypeNode; //ICompiledTypeNode ctn = value.real_parameters[i].type as ICompiledTypeNode;
ICompiledTypeNode ctn2 = parameters[i].type as ICompiledTypeNode; ICompiledTypeNode ctn2 = parameters[i].type as ICompiledTypeNode;
ITypeNode ctn3 = real_parameters[i].type; ITypeNode ctn3 = real_parameters[i].type;
ITypeNode ctn4 = real_parameters[i].conversion_type;
if (ctn2 != null && !(real_parameters[i] is SemanticTree.INullConstantNode) && (ctn3.is_value_type || ctn3.is_generic_parameter) && ctn2.compiled_type == TypeFactory.ObjectType) if (ctn2 != null && !(real_parameters[i] is SemanticTree.INullConstantNode) && (ctn3.is_value_type || ctn3.is_generic_parameter) && ctn2.compiled_type == TypeFactory.ObjectType)
il.Emit(OpCodes.Box, helper.GetTypeReference(ctn3).tp); il.Emit(OpCodes.Box, helper.GetTypeReference(ctn3).tp);
else if (ctn2 != null && !(real_parameters[i] is SemanticTree.INullConstantNode) && ctn4 != null && (ctn4.is_value_type || ctn4.is_generic_parameter) && ctn2.compiled_type == TypeFactory.ObjectType)
il.Emit(OpCodes.Box, helper.GetTypeReference(ctn4).tp);
is_addr = false; is_addr = false;
} }
//вызов метода //вызов метода
@ -6692,10 +6688,12 @@ namespace PascalABCCompiler.NETGenerator
is_dot_expr = true; is_dot_expr = true;
//DarkStar Fixed: type t:=i.gettype(); //DarkStar Fixed: type t:=i.gettype();
bool _box = value.obj.type.is_value_type && !value.compiled_method.method_info.DeclaringType.IsValueType; bool _box = value.obj.type.is_value_type && !value.compiled_method.method_info.DeclaringType.IsValueType;
if (!_box && value.obj.conversion_type != null)
_box = value.obj.conversion_type != null && value.obj.conversion_type.is_value_type;
if (_box) if (_box)
is_dot_expr = false; is_dot_expr = false;
value.obj.visit(this); value.obj.visit(this);
if ((value.obj.type.is_value_type) && !value.compiled_method.method_info.DeclaringType.IsValueType) if (value.obj.type.is_value_type && !value.compiled_method.method_info.DeclaringType.IsValueType)
{ {
il.Emit(OpCodes.Box, helper.GetTypeReference(value.obj.type).tp); il.Emit(OpCodes.Box, helper.GetTypeReference(value.obj.type).tp);
} }
@ -6705,6 +6703,10 @@ namespace PascalABCCompiler.NETGenerator
il.Emit(OpCodes.Stloc, lb); il.Emit(OpCodes.Stloc, lb);
il.Emit(OpCodes.Ldloca, lb); il.Emit(OpCodes.Ldloca, lb);
} }
else if (value.obj.conversion_type != null && value.obj.conversion_type.is_value_type && !value.compiled_method.method_info.DeclaringType.IsValueType)
{
il.Emit(OpCodes.Box, helper.GetTypeReference(value.obj.conversion_type).tp);
}
is_dot_expr = false; is_dot_expr = false;
EmitArguments(parameters, real_parameters); EmitArguments(parameters, real_parameters);
/*for (int i = 0; i < real_parameters.Length; i++) /*for (int i = 0; i < real_parameters.Length; i++)
@ -6847,7 +6849,7 @@ namespace PascalABCCompiler.NETGenerator
MethodInfo mi = meth.mi; MethodInfo mi = meth.mi;
IExpressionNode[] real_parameters = value.real_parameters; IExpressionNode[] real_parameters = value.real_parameters;
bool tmp_dot = is_dot_expr; bool tmp_dot = is_dot_expr;
if (tmp_dot == false) if (!tmp_dot)
is_dot_expr = true; is_dot_expr = true;
value.obj.visit(this); value.obj.visit(this);
if ((value.obj.type.is_value_type) && !value.method.common_comprehensive_type.is_value_type) if ((value.obj.type.is_value_type) && !value.method.common_comprehensive_type.is_value_type)
@ -6860,6 +6862,10 @@ namespace PascalABCCompiler.NETGenerator
il.Emit(OpCodes.Stloc, lb); il.Emit(OpCodes.Stloc, lb);
il.Emit(OpCodes.Ldloca, lb); il.Emit(OpCodes.Ldloca, lb);
} }
else if (value.obj.conversion_type != null && value.obj.conversion_type.is_value_type && !value.method.common_comprehensive_type.is_value_type)
{
il.Emit(OpCodes.Box, helper.GetTypeReference(value.obj.conversion_type).tp);
}
is_dot_expr = false; is_dot_expr = false;
//bool is_comp_gen = false; //bool is_comp_gen = false;
//bool need_fee = false; //bool need_fee = false;
@ -6939,9 +6945,7 @@ namespace PascalABCCompiler.NETGenerator
{ {
TypeInfo ti = helper.GetTypeReference(parameter.type); TypeInfo ti = helper.GetTypeReference(parameter.type);
if (ti != null && ti.clone_meth != null && parameter.parameter_type == parameter_type.value && !parameter.is_const && if (ti != null && ti.clone_meth != null && parameter.parameter_type == parameter_type.value && !parameter.is_const &&
parameter.type.type_special_kind != type_special_kind.base_set_type /*&& parameter.type.type_special_kind != type_special_kind.base_set_type)
!(expr is ICompiledConstructorCall) &&
!(expr is ICommonConstructorCall)*/)
{ {
il.Emit(OpCodes.Call, ti.clone_meth); il.Emit(OpCodes.Call, ti.clone_meth);
return true; return true;
@ -7539,6 +7543,10 @@ namespace PascalABCCompiler.NETGenerator
{ {
il.Emit(OpCodes.Box, helper.GetTypeReference(from.type).tp); il.Emit(OpCodes.Box, helper.GetTypeReference(from.type).tp);
} }
else if (from.conversion_type != null && (from.type.is_value_type || from.type.is_generic_parameter) && ctn2 != null && ctn2.compiled_type == TypeFactory.ObjectType)
{
il.Emit(OpCodes.Box, helper.GetTypeReference(from.conversion_type).tp);
}
CheckArrayAssign(to, from, il); CheckArrayAssign(to, from, il);
} }
@ -7925,6 +7933,10 @@ namespace PascalABCCompiler.NETGenerator
{ {
il.Emit(OpCodes.Box, helper.GetTypeReference(from.type).tp); il.Emit(OpCodes.Box, helper.GetTypeReference(from.type).tp);
} }
else if (from.conversion_type != null && (from.conversion_type.is_value_type || from.conversion_type.is_generic_parameter) && ctn2 != null && ctn2.compiled_type == TypeFactory.ObjectType)
{
il.Emit(OpCodes.Box, helper.GetTypeReference(from.conversion_type).tp);
}
CheckArrayAssign(to, from, il); CheckArrayAssign(to, from, il);
if (value.indices == null) if (value.indices == null)
@ -7958,6 +7970,10 @@ namespace PascalABCCompiler.NETGenerator
{ {
il.Emit(OpCodes.Box, helper.GetTypeReference(from.type).tp); il.Emit(OpCodes.Box, helper.GetTypeReference(from.type).tp);
} }
else if (from.conversion_type != null && (from.conversion_type.is_value_type || from.conversion_type.is_generic_parameter) && ctn2 != null && ctn2.compiled_type == TypeFactory.ObjectType)
{
il.Emit(OpCodes.Box, helper.GetTypeReference(from.conversion_type).tp);
}
CheckArrayAssign(to, from, il); CheckArrayAssign(to, from, il);
NETGeneratorTools.PushStind(il, ti.tp); NETGeneratorTools.PushStind(il, ti.tp);
if (TypeNeedToFix(value.type)) if (TypeNeedToFix(value.type))
@ -9185,6 +9201,8 @@ namespace PascalABCCompiler.NETGenerator
cmcall.obj.visit(this); cmcall.obj.visit(this);
if (cmcall.obj.type.is_value_type) if (cmcall.obj.type.is_value_type)
il.Emit(OpCodes.Box, helper.GetTypeReference(cmcall.obj.type).tp); il.Emit(OpCodes.Box, helper.GetTypeReference(cmcall.obj.type).tp);
else if (cmcall.obj.conversion_type != null && cmcall.obj.conversion_type.is_value_type)
il.Emit(OpCodes.Box, helper.GetTypeReference(cmcall.obj.conversion_type).tp);
return; return;
} }
SemanticTree.ICommonStaticMethodCallNode csmcall = ifc as SemanticTree.ICommonStaticMethodCallNode; SemanticTree.ICommonStaticMethodCallNode csmcall = ifc as SemanticTree.ICommonStaticMethodCallNode;
@ -9199,6 +9217,8 @@ namespace PascalABCCompiler.NETGenerator
cmccall.obj.visit(this); cmccall.obj.visit(this);
if (cmccall.obj.type.is_value_type) if (cmccall.obj.type.is_value_type)
il.Emit(OpCodes.Box, helper.GetTypeReference(cmccall.obj.type).tp); il.Emit(OpCodes.Box, helper.GetTypeReference(cmccall.obj.type).tp);
else if (cmccall.obj.conversion_type != null && cmccall.obj.conversion_type.is_value_type)
il.Emit(OpCodes.Box, helper.GetTypeReference(cmccall.obj.conversion_type).tp);
return; return;
} }
SemanticTree.ICompiledStaticMethodCallNode csmcall2 = ifc as SemanticTree.ICompiledStaticMethodCallNode; SemanticTree.ICompiledStaticMethodCallNode csmcall2 = ifc as SemanticTree.ICompiledStaticMethodCallNode;

View file

@ -384,7 +384,7 @@ namespace PascalABCCompiler
private void VisitStatement(statement_node sn) private void VisitStatement(statement_node sn)
{ {
if (sn == null) return; if (sn == null) return;
if (!(sn is statements_list) && is_break_stmt && !has_goto) if (!(sn is statements_list) && is_break_stmt && !has_goto && !(sn is empty_statement))
{ {
warns.Add(new UnreachableCodeDetected(sn.location)); warns.Add(new UnreachableCodeDetected(sn.location));
is_break_stmt = false; is_break_stmt = false;

View file

@ -1,10 +1,19 @@
procedure test2(params arr: array of object);
begin
assert(integer(arr[0]) = 123);
end;
procedure test(o: object); procedure test(o: object);
begin begin
assert(integer(o) = 123); assert(integer(o) = 123);
end; end;
begin begin
var i := 123; var i := 123;
var j := object(i); var j := object(i);
assert(integer(j) = 123); assert(integer(j) = 123);
test(object(i)); test(object(i));
test2(object(i),2);
writeln(object(i).ToString);
assert(object(i).ToString = '123');
end. end.