aboutsummaryrefslogtreecommitdiff
path: root/lib/CodeGen/ExpressionGen.cc
diff options
context:
space:
mode:
author_ov4 <ov4@ov4.org>2026-10-17 05:27:14 +0000
committer_ov4 <ov4@ov4.org>2026-10-17 05:27:14 +0000
commite782898e420c7f2abd83b97c160194d0e70598dd (patch)
treef1d95ee7b2766ac2f443df0cb6d5ba419085649e /lib/CodeGen/ExpressionGen.cc
parent42c1649264153940de143741337c38042c32e60b (diff)
feat(calls): support standalone calls and void pointer casts
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Diffstat (limited to 'lib/CodeGen/ExpressionGen.cc')
-rw-r--r--lib/CodeGen/ExpressionGen.cc213
1 files changed, 109 insertions, 104 deletions
diff --git a/lib/CodeGen/ExpressionGen.cc b/lib/CodeGen/ExpressionGen.cc
index b3655fd..fa2581f 100644
--- a/lib/CodeGen/ExpressionGen.cc
+++ b/lib/CodeGen/ExpressionGen.cc
@@ -124,110 +124,8 @@ Value *CodeGen::emitExpr(ExprAST *Expr) {
return emitBinaryOp(Bin->getOp(), L, LT, R, RT, Bin->getLine());
}
- if (auto *Call = dynamic_cast<CallExprAST*>(Expr)) {
- std::string Name = Call->getCallee();
- if (const BuiltinInfo *B = findBuiltin(Name)) {
- Name = B->Name;
- if (Call->getArgs().size() != B->Arity) {
- reportError("%s expects %u arg%s", B->Name, B->Arity, B->Arity == 1 ? "" : "s");
- return nullptr;
- }
- }
- if (Name == "LENGTH") {
- Value *Str = emitCoercedExpr(Call->getArgs()[0].get(), resolveType("STRING"));
- if (!Str) return nullptr;
- return StrHandler->emitLength(Str);
- }
- if (Name == "MID") {
- Value *Str = emitCoercedExpr(Call->getArgs()[0].get(), resolveType("STRING"));
- Value *Start = emitCoercedExpr(Call->getArgs()[1].get(), resolveType("INTEGER"));
- Value *Len = emitCoercedExpr(Call->getArgs()[2].get(), resolveType("INTEGER"));
- if (!Str || !Start || !Len) return nullptr;
- return StrHandler->emitMid(Str, Start, Len);
- }
- if (Name == "RIGHT") {
- Value *Str = emitCoercedExpr(Call->getArgs()[0].get(), resolveType("STRING"));
- Value *Len = emitCoercedExpr(Call->getArgs()[1].get(), resolveType("INTEGER"));
- if (!Str || !Len) return nullptr;
- return StrHandler->emitRight(Str, Len);
- }
- if (Name == "LEFT") {
- Value *Str = emitCoercedExpr(Call->getArgs()[0].get(), resolveType("STRING"));
- Value *Len = emitCoercedExpr(Call->getArgs()[1].get(), resolveType("INTEGER"));
- if (!Str || !Len) return nullptr;
- return StrHandler->emitLeft(Str, Len);
- }
- if (Name == "LCASE") {
- Value *Str = emitCoercedExpr(Call->getArgs()[0].get(), resolveType("STRING"));
- if (!Str) return nullptr;
- return StrHandler->emitLCase(Str);
- }
- if (Name == "UCASE") {
- Value *Str = emitCoercedExpr(Call->getArgs()[0].get(), resolveType("STRING"));
- if (!Str) return nullptr;
- return StrHandler->emitUCase(Str);
- }
- if (Name == "ASC") {
- const TypeInfo *ArgType = getExprTypeInfo(Call->getArgs()[0].get());
- if (ArgType && (ArgType->isUserKind() || ArgType->isC())) {
- reportError("ASC expects a CHAR or STRING (got %s)", ArgType->Name.c_str());
- return nullptr;
- }
- Value *ArgVal = emitExpr(Call->getArgs()[0].get());
- if (!ArgVal) return nullptr;
- Value *CharVal = nullptr;
- if (ArgType && ArgType->isChar()) {
- CharVal = coerceValueToType(ArgVal, resolveType("CHAR"));
- } else {
- CharVal = Builder->CreateLoad(Type::getInt8Ty(*TheContext), ArgVal, "char_load");
- }
- Value *AscVal = Builder->CreateZExt(CharVal, Type::getInt32Ty(*TheContext), "asc_val");
- return coerceValueToType(AscVal, resolveType("INTEGER"));
- }
- if (Name == "CHR") {
- Value *IntVal = emitCoercedExpr(Call->getArgs()[0].get(), resolveType("INTEGER"));
- if (!IntVal) return nullptr;
- Value *CharVal = Builder->CreateTrunc(IntVal, Type::getInt8Ty(*TheContext), "chr_val");
- return coerceValueToType(CharVal, resolveType("STRING"));
- }
- if (Name == "IS_NUM") {
- Value *Str = emitCoercedExpr(Call->getArgs()[0].get(), resolveType("STRING"));
- if (!Str) return nullptr;
- return StrConvHandler->emitIsNum(Str);
- }
- if (Name == "NUM_TO_STR") {
- const TypeInfo *ArgType = getExprTypeInfo(Call->getArgs()[0].get());
- if (ArgType && (ArgType->isUserKind() || ArgType->isC())) {
- reportError("NUM_TO_STR expects a number (got %s)", ArgType->Name.c_str());
- return nullptr;
- }
- Value *NumV = emitExpr(Call->getArgs()[0].get());
- if (!NumV) return nullptr;
- bool IsReal = NumV->getType()->isDoubleTy();
- if (NumV->getType()->isIntegerTy(8)) {
- NumV = coerceValueToType(NumV, resolveType("INTEGER"));
- }
- return StrConvHandler->emitNumToStr(NumV, IsReal);
- }
- if (Name == "STR_TO_NUM") {
- Value *Str = emitCoercedExpr(Call->getArgs()[0].get(), resolveType("STRING"));
- if (!Str) return nullptr;
- return StrConvHandler->emitStrToNum(Str, true);
- }
- if (Name == "EOF") {
- if (isWholeArrayVar(Call->getArgs()[0].get())) {
- reportError("Cannot use a whole array as the EOF filename");
- return nullptr;
- }
- Value *FileName = emitCoercedExpr(Call->getArgs()[0].get(), resolveType("STRING"));
- if (!FileName) return nullptr;
- return Files->emitEof(FileName, Call->getLine());
- }
-
- std::vector<Value*> Args;
- if (!marshalCallArgs(Name, Call->getArgs(), Call->getLine(), Args)) return nullptr;
- return FuncGen->emitCallExpr(Call, Args);
- }
+ if (auto *Call = dynamic_cast<CallExprAST*>(Expr))
+ return emitCall(Call->getCallee(), Call->getArgs(), Call->getLine());
if (auto *D = dynamic_cast<DesignatorExprAST*>(Expr)) {
LValueInfo LV;
@@ -274,3 +172,110 @@ Value *CodeGen::emitBinaryOp(int Op, Value *L, const TypeInfo *LT,
}
return ArithHandler->emitBinaryOp(Op, L, R, Line);
}
+
+Value *CodeGen::emitCall(const std::string &Callee,
+ const std::vector<std::unique_ptr<ExprAST>> &ArgExprs, int Line) {
+ SaveAndRestore<int> Location(DiagnosticLine, Line ? Line : DiagnosticLine);
+ std::string Name = Callee;
+ if (const BuiltinInfo *B = findBuiltin(Name)) {
+ Name = B->Name;
+ if (ArgExprs.size() != B->Arity) {
+ reportError("%s expects %u arg%s", B->Name, B->Arity, B->Arity == 1 ? "" : "s");
+ return nullptr;
+ }
+ }
+ if (Name == "LENGTH") {
+ Value *Str = emitCoercedExpr(ArgExprs[0].get(), resolveType("STRING"));
+ if (!Str) return nullptr;
+ return StrHandler->emitLength(Str);
+ }
+ if (Name == "MID") {
+ Value *Str = emitCoercedExpr(ArgExprs[0].get(), resolveType("STRING"));
+ Value *Start = emitCoercedExpr(ArgExprs[1].get(), resolveType("INTEGER"));
+ Value *Len = emitCoercedExpr(ArgExprs[2].get(), resolveType("INTEGER"));
+ if (!Str || !Start || !Len) return nullptr;
+ return StrHandler->emitMid(Str, Start, Len);
+ }
+ if (Name == "RIGHT") {
+ Value *Str = emitCoercedExpr(ArgExprs[0].get(), resolveType("STRING"));
+ Value *Len = emitCoercedExpr(ArgExprs[1].get(), resolveType("INTEGER"));
+ if (!Str || !Len) return nullptr;
+ return StrHandler->emitRight(Str, Len);
+ }
+ if (Name == "LEFT") {
+ Value *Str = emitCoercedExpr(ArgExprs[0].get(), resolveType("STRING"));
+ Value *Len = emitCoercedExpr(ArgExprs[1].get(), resolveType("INTEGER"));
+ if (!Str || !Len) return nullptr;
+ return StrHandler->emitLeft(Str, Len);
+ }
+ if (Name == "LCASE") {
+ Value *Str = emitCoercedExpr(ArgExprs[0].get(), resolveType("STRING"));
+ if (!Str) return nullptr;
+ return StrHandler->emitLCase(Str);
+ }
+ if (Name == "UCASE") {
+ Value *Str = emitCoercedExpr(ArgExprs[0].get(), resolveType("STRING"));
+ if (!Str) return nullptr;
+ return StrHandler->emitUCase(Str);
+ }
+ if (Name == "ASC") {
+ const TypeInfo *ArgType = getExprTypeInfo(ArgExprs[0].get());
+ if (ArgType && (ArgType->isUserKind() || ArgType->isC())) {
+ reportError("ASC expects a CHAR or STRING (got %s)", ArgType->Name.c_str());
+ return nullptr;
+ }
+ Value *ArgVal = emitExpr(ArgExprs[0].get());
+ if (!ArgVal) return nullptr;
+ Value *CharVal = nullptr;
+ if (ArgType && ArgType->isChar()) {
+ CharVal = coerceValueToType(ArgVal, resolveType("CHAR"));
+ } else {
+ CharVal = Builder->CreateLoad(Type::getInt8Ty(*TheContext), ArgVal, "char_load");
+ }
+ Value *AscVal = Builder->CreateZExt(CharVal, Type::getInt32Ty(*TheContext), "asc_val");
+ return coerceValueToType(AscVal, resolveType("INTEGER"));
+ }
+ if (Name == "CHR") {
+ Value *IntVal = emitCoercedExpr(ArgExprs[0].get(), resolveType("INTEGER"));
+ if (!IntVal) return nullptr;
+ Value *CharVal = Builder->CreateTrunc(IntVal, Type::getInt8Ty(*TheContext), "chr_val");
+ return coerceValueToType(CharVal, resolveType("STRING"));
+ }
+ if (Name == "IS_NUM") {
+ Value *Str = emitCoercedExpr(ArgExprs[0].get(), resolveType("STRING"));
+ if (!Str) return nullptr;
+ return StrConvHandler->emitIsNum(Str);
+ }
+ if (Name == "NUM_TO_STR") {
+ const TypeInfo *ArgType = getExprTypeInfo(ArgExprs[0].get());
+ if (ArgType && (ArgType->isUserKind() || ArgType->isC())) {
+ reportError("NUM_TO_STR expects a number (got %s)", ArgType->Name.c_str());
+ return nullptr;
+ }
+ Value *NumV = emitExpr(ArgExprs[0].get());
+ if (!NumV) return nullptr;
+ bool IsReal = NumV->getType()->isDoubleTy();
+ if (NumV->getType()->isIntegerTy(8)) {
+ NumV = coerceValueToType(NumV, resolveType("INTEGER"));
+ }
+ return StrConvHandler->emitNumToStr(NumV, IsReal);
+ }
+ if (Name == "STR_TO_NUM") {
+ Value *Str = emitCoercedExpr(ArgExprs[0].get(), resolveType("STRING"));
+ if (!Str) return nullptr;
+ return StrConvHandler->emitStrToNum(Str, true);
+ }
+ if (Name == "EOF") {
+ if (isWholeArrayVar(ArgExprs[0].get())) {
+ reportError("Cannot use a whole array as the EOF filename");
+ return nullptr;
+ }
+ Value *FileName = emitCoercedExpr(ArgExprs[0].get(), resolveType("STRING"));
+ if (!FileName) return nullptr;
+ return Files->emitEof(FileName, Line);
+ }
+
+ std::vector<Value*> Args;
+ if (!marshalCallArgs(Name, ArgExprs, Line, Args)) return nullptr;
+ return FuncGen->emitCall(Name, Args);
+}