From 760233cb9db882f665722d21a9df017db4800f87 Mon Sep 17 00:00:00 2001 From: Sharivan Date: Wed, 18 Sep 2024 15:44:28 -0300 Subject: [PATCH] - Atualizado o exemplo de teste TesteUnidade.sl MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Corrigido um problema na concatenação de strings com tipos numéricos quando o tipo da string é contado por referência. --- Comp/Expr/CompilerBinaryExpression.cs | 51 +++++++++++++++++++++------ examples/TesteUnidades.sl | 15 ++++---- 2 files changed, 47 insertions(+), 19 deletions(-) diff --git a/Comp/Expr/CompilerBinaryExpression.cs b/Comp/Expr/CompilerBinaryExpression.cs index b04c088..91216be 100644 --- a/Comp/Expr/CompilerBinaryExpression.cs +++ b/Comp/Expr/CompilerBinaryExpression.cs @@ -941,32 +941,61 @@ private AbstractType CompileBinaryExpression(Context context, Assembler assemble case StringType: { + Assembler beforeLeftAssembler = new(); Assembler beforeRightAssembler = new(); Variable rightCastTempVar = null; - if (rightType is PointerType rptr) - { - if (!PrimitiveType.IsPrimitiveChar(rptr.Type)) - throw new CompilerException(rightOperand.Interval, $"Concatenação de strings não pode ser feita com um ponteiro do tipo '{rptr.Type}'."); - CompileCast(context, rightAssembler, beforeRightAssembler, rightType, leftType, false, rightOperand.Interval, out rightCastTempVar); - } - else if (rightType is not StringType) + CompileCast(context, leftAssembler, beforeLeftAssembler, leftType, StringType.STRING, false, leftOperand.Interval, out var leftCastTempVar); + + switch (rightType) { - throw new CompilerException(rightOperand.Interval, $"Concatenação de strings não pode ser feita com o tipo '{rightType}'."); + case PrimitiveType rp: // Concatenação de uma string com um tipo primitivo, isso exige a conversão do primitivo para string para então realizar a concatenação + { + var rightTempVar = context.AcquireTemporaryVariable(StringType.STRING, rightOperand.Interval); + beforeRightAssembler.EmitLoadLocalHostAddress(rightTempVar.Offset); + + var func = rp.Primitive switch + { + Primitive.BOOL => unitySystem.FindFunction("BoolParaTexto"), + Primitive.CHAR => unitySystem.FindFunction("CharParaTexto"), + Primitive.BYTE or Primitive.SHORT or Primitive.INT => unitySystem.FindFunction("IntParaTexto"), + Primitive.LONG => unitySystem.FindFunction("LongParaTexto"), + Primitive.FLOAT => unitySystem.FindFunction("FloatParaTexto"), + Primitive.DOUBLE => unitySystem.FindFunction("DoubleParaTexto"), + _ => throw new CompilerException(rightOperand.Interval, "Operando inválido."), + }; + int index = GetOrAddExternalFunction(func.Name, func.ParameterSize); + rightAssembler.EmitExternCall(index); + rightAssembler.EmitLoadLocalPtr(rightTempVar.Offset); + break; + } + + case PointerType rptr: + { + if (!PrimitiveType.IsPrimitiveChar(rptr.Type)) + throw new CompilerException(rightOperand.Interval, $"Concatenação de strings não pode ser feita com um ponteiro do tipo '{rptr.Type}'."); + + CompileCast(context, rightAssembler, beforeRightAssembler, rightType, leftType, false, rightOperand.Interval, out rightCastTempVar); + break; + } + + default: + throw new CompilerException(rightOperand.Interval, $"Concatenação de strings não pode ser feita com o tipo '{rightType}'."); } tempVar = context.AcquireTemporaryVariable(StringType.STRING, expression.Interval); assembler.EmitLoadLocalHostAddress(tempVar.Offset); + assembler.Emit(beforeLeftAssembler); assembler.Emit(leftAssembler); assembler.Emit(beforeRightAssembler); assembler.Emit(rightAssembler); rightCastTempVar?.Release(); - var func = unitySystem.FindFunction("ConcatenaTextos2"); - int index = GetOrAddExternalFunction(func.Name, func.ParameterSize); - assembler.EmitExternCall(index); + var concat = unitySystem.FindFunction("ConcatenaTextos2"); + int concatIndex = GetOrAddExternalFunction(concat.Name, concat.ParameterSize); + assembler.EmitExternCall(concatIndex); assembler.EmitLoadLocalPtr(tempVar.Offset); diff --git a/examples/TesteUnidades.sl b/examples/TesteUnidades.sl index 72160d8..f9b69f8 100644 --- a/examples/TesteUnidades.sl +++ b/examples/TesteUnidades.sl @@ -5,22 +5,21 @@ usando Sorts; { // Teste da unidade padrão System: - var str:char[256]; - CopiaString("abcdefgh", str); - ConcatenaStrings(str, str, "1234567890"); - escrevaln "\"abcdefgh\"+\"1234567890\"=\"", str, '"'; + var str:texto = "abcdefgh"; // string dinâmica contada por referência + str = str + 1234567890; // concatenação de string com tipos numéricos + escrevaln "\"abcdefgh\" + \"1234567890\" = \"", str, '"'; - escrevaln "ComprimentoString(\"", str, "\")=", ComprimentoString(str); + escrevaln "Tamanho do texto \"", str, "\" = ", str.tamanho; - var str2:char[16]; + var str2:char[16]; // string estática CopiaString("4567", str2); var str2Int:int; StringParaInt(str2, str2Int); escrevaln "StringParaInt(\"", str2, "\")=", str2Int; // saída esperada: - // "abcdefgh"+"1234567890"="abcdefgh1234567890" - // ComprimentoString("abcdefgh1234567890")=18; + // "abcdefgh" + "1234567890" = "abcdefgh1234567890" + // Tamanho do texto "abcdefgh1234567890" = 18; // StringParaInt("4567")=4567 // Teste da unidade Sorts: