This commit is contained in:
Бондарев Иван 2017-07-02 12:18:56 +02:00
parent c710f86dcb
commit d739395527
10 changed files with 80 additions and 19 deletions

View file

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

View file

@ -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());

View file

@ -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]);

View file

@ -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;
}

View file

@ -525,6 +525,11 @@ namespace PascalABCCompiler.SemanticTree
{
get;
}
ITypeNode conversion_type
{
get;
}
}
//Базовый интерфейс для вызовов функций. Нигде не создается.

10
TestSuite/boxing1.pas Normal file
View 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.

View 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.

View file

@ -0,0 +1 @@
uses u_boxing1; begin end.

View file

@ -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;
}

View file

@ -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]