aboutsummaryrefslogtreecommitdiff
path: root/lib/CodeGen/ExpressionGen.cc
diff options
context:
space:
mode:
author_ov4 <ov4@ov4.org>2026-10-22 15:07:27 +0000
committer_ov4 <ov4@ov4.org>2026-10-22 15:21:14 +0000
commitf14b50d776ec743bd62fda22a9c154bba9588840 (patch)
tree753196ff7881d0bfbcc29834277ffc14e2b4f440 /lib/CodeGen/ExpressionGen.cc
parent8802a5d740d6cff29e473e7e0507b6a6d40a55e4 (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.cc27
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);
}