From 713a313b06256a13ddefa5e257e3b80f8aa808ba Mon Sep 17 00:00:00 2001 From: _ov4 Date: Thu, 22 Oct 2026 15:32:49 +0000 Subject: feat(codegen): convert implicitly between CHAR and STRING A CHAR becomes a one-character STRING in &, comparisons, assignment, parameter passing and RETURN. A STRING becomes a CHAR in assignment, parameter passing and RETURN, with a runtime error when its length is not 1. CHAR with INTEGER or BOOLEAN still does not convert. Co-Authored-By: Claude Sonnet 5.5 --- lib/CodeGen/ConstructorGen.cc | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) (limited to 'lib/CodeGen/ConstructorGen.cc') diff --git a/lib/CodeGen/ConstructorGen.cc b/lib/CodeGen/ConstructorGen.cc index 286435e..e956f9d 100644 --- a/lib/CodeGen/ConstructorGen.cc +++ b/lib/CodeGen/ConstructorGen.cc @@ -22,9 +22,11 @@ Value *CodeGen::emitOwnedValue(ExprAST *Expr, const TypeInfo *Type, std::vector &Transfers) { if (!Type || (!Type->IsClass && !containsString(Type))) return emitCoercedExpr(Expr, Type); const TypeInfo *Source = getExprTypeInfo(Expr); - if (!Source || !Source->sameType(Type)) return emitCoercedExpr(Expr, Type); + // A CHAR argument becomes a fresh STRING temporary, owned like any other. + bool FromChar = Source && Type->isString() && Source->Kind == TypeKind::Char; + if (!Source || (!Source->sameType(Type) && !FromChar)) return emitCoercedExpr(Expr, Type); Value *Value = nullptr; - if (isObjectLValue(Expr)) { + if (!FromChar && isObjectLValue(Expr)) { LValueInfo LV; const auto *Var = dynamic_cast(Expr); const auto *Symbol = Var ? getSymbolInfo(Var->getName()) : nullptr; @@ -172,8 +174,11 @@ void CodeGen::emitAssignment(const LValueInfo &Target, ExprAST *Expr, const Symb } return; } - if (Info && Info->IsClass) { - auto Resolution = resolveOperator(tok_assign, Info, getExprTypeInfo(Expr)); + const TypeInfo *ExprType = getExprTypeInfo(Expr); + // A CHAR assigned to a STRING is converted first, not bound to OPERATOR<-. + bool CharToString = Info && Info->isString() && ExprType && ExprType->Kind == TypeKind::Char; + if (Info && Info->IsClass && !CharToString) { + auto Resolution = resolveOperator(tok_assign, Info, ExprType); if (Resolution.Ambiguous) { reportError("Ambiguous assignment operator"); return; @@ -190,7 +195,9 @@ void CodeGen::emitAssignment(const LValueInfo &Target, ExprAST *Expr, const Symb Value *Val = emitCoercedExpr(Expr, Info); if (!Val) return; std::vector Transfers; - bool CopySource = isObjectLValue(Expr); + // Only a value of the same type is an existing object to copy; a + // converted one is already a fresh temporary. + bool CopySource = isObjectLValue(Expr) && ExprType && ExprType->sameType(Info); if (!CopySource) { materializeOperatorReceiver(Val, Info); if (typeNeedsDestruction(Info->Name)) Transfers.push_back(StackObjects.size() - 1); -- cgit v1.3.1-4-g156e