diff options
| author | _ov4 <ov4@ov4.org> | 2026-10-22 15:07:27 +0000 |
|---|---|---|
| committer | _ov4 <ov4@ov4.org> | 2026-10-22 15:21:14 +0000 |
| commit | f14b50d776ec743bd62fda22a9c154bba9588840 (patch) | |
| tree | 753196ff7881d0bfbcc29834277ffc14e2b4f440 /lib/CodeGen/ExpressionGen.cc | |
| parent | 8802a5d740d6cff29e473e7e0507b6a6d40a55e4 (diff) | |
feat(codegen)!: reject implicit BOOLEAN, CHAR and INTEGER mixing
Arithmetic and unary minus accept only INTEGER and REAL, AND/OR/NOT need
BOOLEAN, comparisons need equal types (or INTEGER with REAL), and only
INTEGER converts implicitly to REAL. Use ASC and CHR for characters.
No existing test program relied on the now-illegal mixing, so none changed.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Diffstat (limited to 'lib/CodeGen/ExpressionGen.cc')
| -rw-r--r-- | lib/CodeGen/ExpressionGen.cc | 27 |
1 files changed, 27 insertions, 0 deletions
diff --git a/lib/CodeGen/ExpressionGen.cc b/lib/CodeGen/ExpressionGen.cc index d7a4ba7..0434348 100644 --- a/lib/CodeGen/ExpressionGen.cc +++ b/lib/CodeGen/ExpressionGen.cc @@ -106,6 +106,10 @@ Value *CodeGen::emitExpr(ExprAST *Expr) { reportError("Unary '-' requires a supported numeric operand"); return nullptr; } + if (Info->Kind == TypeKind::Boolean || Info->Kind == TypeKind::Char) { + reportError("Unary '-' cannot be applied to %s", Info->Name.c_str()); + return nullptr; + } Value *Operand = emitExpr(Unary->getOperand()); if (!Operand) return nullptr; return ArithHandler->emitBinaryOp('-', ConstantInt::get(Type::getInt64Ty(*TheContext), 0), @@ -188,6 +192,29 @@ Value *CodeGen::emitBinaryOp(int Op, Value *L, const TypeInfo *LT, return emitCBinaryOp(Op, L, LT, R, RT, Line); if ((LT && LT->isUserKind()) || (RT && RT->isUserKind())) return emitUserKindBinaryOp(Op, L, LT, R, RT, Line); + + // Plain scalars only: BOOLEAN and CHAR are not numbers (use ASC / CHR), + // AND / OR take BOOLEAN, comparisons need equal types or INTEGER with REAL. + auto Numeric = [](const TypeInfo *T) { + return T->Kind == TypeKind::Integer || T->Kind == TypeKind::Real; + }; + bool Ok = true; + switch (Op) { + case '+': case '-': case '*': case '/': case tok_div: case tok_mod: + Ok = Numeric(LT) && Numeric(RT); + break; + case tok_and: case tok_or: + Ok = LT->Kind == TypeKind::Boolean && RT->Kind == TypeKind::Boolean; + break; + case tok_eq: case tok_ne: case '<': case '>': case tok_le: case tok_ge: + Ok = LT->Kind == RT->Kind || (Numeric(LT) && Numeric(RT)); + break; + } + if (!Ok) { + reportError("Operator %s cannot be applied to %s and %s", + operatorSpelling(Op).c_str(), LT->Name.c_str(), RT->Name.c_str()); + return nullptr; + } return ArithHandler->emitBinaryOp(Op, L, R, Line); } |
