bug fix #428
This commit is contained in:
parent
c710f86dcb
commit
d739395527
|
|
@ -6,6 +6,6 @@ namespace PascalABCCompiler.PCU
|
|||
{
|
||||
public static class PCUFileFormatVersion
|
||||
{
|
||||
public static System.Int16 Version = 106;
|
||||
public static System.Int16 Version = 107;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3873,27 +3873,16 @@ namespace PascalABCCompiler.PCU
|
|||
|
||||
private expression_node CreateBasicFunctionCall()
|
||||
{
|
||||
/*SemanticTree.basic_function_type bft = (SemanticTree.basic_function_type)br.ReadInt16();
|
||||
type_node _tn = GetTypeReference();
|
||||
int num_param = br.ReadInt32();
|
||||
basic_function_node bfn = new basic_function_node(bft, _tn, true);
|
||||
basic_function_call bfc = new basic_function_call(bfn, null);
|
||||
bfc.ret_type=_tn;
|
||||
for (int i = 0; i < num_param; i++)
|
||||
{
|
||||
expression_node expr=CreateExpression();
|
||||
bfc.parameters.AddElement(expr);
|
||||
bfn.parameters.AddElement(new basic_parameter("p",expr.type, PascalABCCompiler.SemanticTree.parameter_type.value, bfn));
|
||||
}
|
||||
return bfc;*/
|
||||
SemanticTree.basic_function_type bft = (SemanticTree.basic_function_type)br.ReadInt16();
|
||||
basic_function_node bfn = PascalABCCompiler.SystemLibrary.SystemLibrary.find_operator(bft);
|
||||
if (bfn == null) throw new CompilerInternalError("[PCUREADER] Function not defined: "+bft.ToString());//Console.WriteLine(bft);
|
||||
|
||||
type_node _tn = GetTypeReference();
|
||||
type_node _conversion_tn = GetTypeReference();
|
||||
br.ReadInt32();
|
||||
basic_function_call bfc = new basic_function_call(bfn,null);
|
||||
bfc.ret_type = _tn;
|
||||
bfc.conversion_type = _conversion_tn;
|
||||
int num_param = bfn.parameters.Count;
|
||||
for (int i=0; i<num_param; i++)
|
||||
bfc.parameters.AddElement(CreateExpression());
|
||||
|
|
|
|||
|
|
@ -3764,6 +3764,7 @@ namespace PascalABCCompiler.PCU
|
|||
{
|
||||
bw.Write((System.Int16)expr.function_node.basic_function_type);
|
||||
WriteTypeReference(expr.ret_type);
|
||||
WriteTypeReference(expr.conversion_type);
|
||||
bw.Write(expr.parameters.Count);
|
||||
for (int i=0; i<expr.parameters.Count; i++)
|
||||
VisitExpression(expr.parameters[i]);
|
||||
|
|
|
|||
|
|
@ -7302,10 +7302,20 @@ namespace PascalABCCompiler.NETGenerator
|
|||
ITypeNode tn2 = parameters[i].type;
|
||||
ICompiledTypeNode ctn2 = tn2 as ICompiledTypeNode;
|
||||
ITypeNode ctn3 = real_parameters[i].type;
|
||||
ITypeNode ctn4 = real_parameters[i].conversion_type;
|
||||
bool use_stn4 = false;
|
||||
//(ssyy) 07.12.2007 При боксировке нужно вызывать Ldsfld вместо Ldsflda.
|
||||
//Дополнительная проверка введена именно для этого.
|
||||
bool box_awaited =
|
||||
(ctn2 != null && ctn2.compiled_type == TypeFactory.ObjectType || tn2.IsInterface) && !(real_parameters[i] is SemanticTree.INullConstantNode) && (ctn3.is_value_type || ctn3.is_generic_parameter);
|
||||
(ctn2 != null && ctn2.compiled_type == TypeFactory.ObjectType || tn2.IsInterface) && !(real_parameters[i] is SemanticTree.INullConstantNode)
|
||||
&& (ctn3.is_value_type || ctn3.is_generic_parameter);
|
||||
if (!box_awaited && (ctn2 != null && ctn2.compiled_type == TypeFactory.ObjectType || tn2.IsInterface) && !(real_parameters[i] is SemanticTree.INullConstantNode)
|
||||
&& ctn4 != null && ctn4.is_value_type)
|
||||
{
|
||||
box_awaited = true;
|
||||
use_stn4 = true;
|
||||
}
|
||||
|
||||
if (!(real_parameters[i] is INullConstantNode))
|
||||
{
|
||||
ti = helper.GetTypeReference(ctn);
|
||||
|
|
@ -7318,7 +7328,10 @@ namespace PascalABCCompiler.NETGenerator
|
|||
CallCloneIfNeed(il, parameters[i], real_parameters[i]);
|
||||
if (box_awaited)
|
||||
{
|
||||
il.Emit(OpCodes.Box, helper.GetTypeReference(ctn3).tp);
|
||||
if (use_stn4)
|
||||
il.Emit(OpCodes.Box, helper.GetTypeReference(ctn4).tp);
|
||||
else
|
||||
il.Emit(OpCodes.Box, helper.GetTypeReference(ctn3).tp);
|
||||
}
|
||||
is_addr = false;
|
||||
}
|
||||
|
|
@ -7410,6 +7423,10 @@ namespace PascalABCCompiler.NETGenerator
|
|||
il.Emit(OpCodes.Box, helper.GetTypeReference(from.type).tp);//упаковка
|
||||
return true;
|
||||
}
|
||||
if (from.conversion_type != null && from.conversion_type.is_value_type && !(from is SemanticTree.INullConstantNode) && (LocalType == TypeFactory.ObjectType || TypeIsInterface(LocalType)))
|
||||
{
|
||||
il.Emit(OpCodes.Box, helper.GetTypeReference(from.conversion_type).tp);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -525,6 +525,11 @@ namespace PascalABCCompiler.SemanticTree
|
|||
{
|
||||
get;
|
||||
}
|
||||
|
||||
ITypeNode conversion_type
|
||||
{
|
||||
get;
|
||||
}
|
||||
}
|
||||
|
||||
//Базовый интерфейс для вызовов функций. Нигде не создается.
|
||||
|
|
|
|||
10
TestSuite/boxing1.pas
Normal file
10
TestSuite/boxing1.pas
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
procedure test(o: object);
|
||||
begin
|
||||
assert(integer(o) = 123);
|
||||
end;
|
||||
begin
|
||||
var i := 123;
|
||||
var j := object(i);
|
||||
assert(integer(j) = 123);
|
||||
test(object(i));
|
||||
end.
|
||||
11
TestSuite/units/u_boxing1.pas
Normal file
11
TestSuite/units/u_boxing1.pas
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
unit u_boxing1;
|
||||
procedure test(o: object);
|
||||
begin
|
||||
assert(integer(o) = 123);
|
||||
end;
|
||||
begin
|
||||
var i := 123;
|
||||
var j := object(i);
|
||||
assert(integer(j) = 123);
|
||||
test(object(i));
|
||||
end.
|
||||
1
TestSuite/usesunits/use_boxing1.pas
Normal file
1
TestSuite/usesunits/use_boxing1.pas
Normal file
|
|
@ -0,0 +1 @@
|
|||
uses u_boxing1; begin end.
|
||||
|
|
@ -638,7 +638,9 @@ namespace PascalABCCompiler.TreeConverter
|
|||
#if (DEBUG)
|
||||
check_operator(pct.first.convertion_method);
|
||||
#endif
|
||||
expression_node expr = create_simple_function_call(pct.first.convertion_method, en.location, en);
|
||||
type_node conv_type = en.type;
|
||||
expression_node expr = create_simple_function_call(pct.first.convertion_method, en.location, en);
|
||||
expr.conversion_type = conv_type;
|
||||
return expr;
|
||||
}
|
||||
|
||||
|
|
@ -668,10 +670,12 @@ namespace PascalABCCompiler.TreeConverter
|
|||
|
||||
if (ptc.first != null)
|
||||
{
|
||||
type_node conv_type = from.type;
|
||||
expression_node ret = create_simple_function_call(ptc.first.convertion_method, from.location, from);
|
||||
if ((ret is base_function_call))
|
||||
(ret as base_function_call).IsExplicitConversion = true;
|
||||
ret.type = to;
|
||||
ret.conversion_type = conv_type;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -682,10 +686,11 @@ namespace PascalABCCompiler.TreeConverter
|
|||
{
|
||||
AddError(from.location, "CAN_NOT_EXPLICITLY_CONVERT_TYPE_{0}_TO_TYPE_{1}", from.type.PrintableName, to.PrintableName);
|
||||
}
|
||||
type_node conv_type = from.type;
|
||||
expression_node expr = create_simple_function_call(SystemLibrary.SystemLibrary.obj_to_obj, from.location, from);
|
||||
//TODO: Переделать.
|
||||
((base_function_call)expr).ret_type = to;
|
||||
|
||||
((base_function_call)expr).conversion_type = conv_type;
|
||||
((base_function_call)expr).IsExplicitConversion = true;
|
||||
return expr;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -229,7 +229,9 @@ namespace PascalABCCompiler.TreeRealization
|
|||
/// Тип выражения.
|
||||
/// </summary>
|
||||
private type_node _tn;
|
||||
|
||||
|
||||
private type_node _conversion_tn;
|
||||
|
||||
/// <summary>
|
||||
/// Конструктор выражения.
|
||||
/// </summary>
|
||||
|
|
@ -259,6 +261,18 @@ namespace PascalABCCompiler.TreeRealization
|
|||
_tn = value;
|
||||
}
|
||||
}
|
||||
|
||||
public virtual type_node conversion_type
|
||||
{
|
||||
get
|
||||
{
|
||||
return _conversion_tn;
|
||||
}
|
||||
set
|
||||
{
|
||||
_conversion_tn = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Обобщенный тип узла.
|
||||
|
|
@ -303,6 +317,14 @@ namespace PascalABCCompiler.TreeRealization
|
|||
return this.type;
|
||||
}
|
||||
}
|
||||
|
||||
SemanticTree.ITypeNode SemanticTree.IExpressionNode.conversion_type
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.conversion_type;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
|
|
|
|||
Loading…
Reference in a new issue