diff options
| author | _ov4 <ov4@ov4.org> | 2026-10-17 05:08:42 +0000 |
|---|---|---|
| committer | _ov4 <ov4@ov4.org> | 2026-10-17 05:08:42 +0000 |
| commit | a6b8afcfb61e1d321405fe8713beaec2aa6320a2 (patch) | |
| tree | a621462bd6f858d1e78495e8c850a2e7321f4809 /lib | |
| parent | 5c3d4d059ae70ea72b52e89940746d61c1d962db (diff) | |
feat(input): support array elements and member targets
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/CodeGen/CTypeGen.cc | 6 | ||||
| -rw-r--r-- | lib/CodeGen/StatementGen.cc | 29 | ||||
| -rw-r--r-- | lib/Parser/Parser.cc | 19 |
3 files changed, 24 insertions, 30 deletions
diff --git a/lib/CodeGen/CTypeGen.cc b/lib/CodeGen/CTypeGen.cc index 80a7d3b..7623103 100644 --- a/lib/CodeGen/CTypeGen.cc +++ b/lib/CodeGen/CTypeGen.cc @@ -177,7 +177,7 @@ void CodeGen::emitCOutput(Value *Val, const TypeInfo *Info, bool AppendNewline) Builder->CreateCall(PrintfFunc, {Fmt, Val}); } -void CodeGen::emitCInput(const SymbolInfo *Symbol, const TypeInfo *Info) { +void CodeGen::emitCInput(Value *Addr, const TypeInfo *Info) { if (Info->Kind != TypeKind::CScalar || Info->isVoid()) { reportError("INPUT is not supported for C pointer or void type %s", Info->Name.c_str()); return; @@ -191,9 +191,9 @@ void CodeGen::emitCInput(const SymbolInfo *Symbol, const TypeInfo *Info) { Builder->CreateCall(ScanfFunc, {Fmt, Temp}); Value *Input = Builder->CreateLoad(NativeInt->LLVMType, Temp); Value *Bool = convertNumericValue(Input, NativeInt, Info); - Builder->CreateStore(Bool, Symbol->Storage); + Builder->CreateStore(Bool, Addr); return; } Value *Fmt = Builder->CreateGlobalString(Info->CInputFormat, "fmt_c_input", 0, TheModule.get()); - Builder->CreateCall(ScanfFunc, {Fmt, Symbol->Storage}); + Builder->CreateCall(ScanfFunc, {Fmt, Addr}); } diff --git a/lib/CodeGen/StatementGen.cc b/lib/CodeGen/StatementGen.cc index 3ea0670..2c80437 100644 --- a/lib/CodeGen/StatementGen.cc +++ b/lib/CodeGen/StatementGen.cc @@ -121,29 +121,20 @@ void CodeGen::emitStmt(StmtAST *Stmt) { } if (auto *In = dynamic_cast<InputStmtAST*>(Stmt)) { - const SymbolInfo *Info = getSymbolInfo(In->getName()); - if (!Info) { - reportError("Unknown variable name %s", In->getName().c_str()); - return; - } - if (!requireWritable(*Info, In->getName())) return; - if (Info->IsArray) { - reportError("INPUT for entire array %s is not supported", In->getName().c_str()); - return; - } - - const TypeInfo *TypeInfo = resolveType(Info->TypeName); + LValueInfo Target; + if (!emitLValue(In->getTarget(), Target)) return; + const TypeInfo *TypeInfo = resolveType(Target.TypeName); if (!TypeInfo) { - reportError("Unknown type for INPUT %s", In->getName().c_str()); + reportError("Unknown type for INPUT %s", Target.TypeName.c_str()); return; } std::vector<Value*> Args; if (TypeInfo->isC()) { - emitCInput(Info, TypeInfo); + emitCInput(Target.Addr, TypeInfo); } else if (TypeInfo->isReal()) { Args.push_back(ScanfFloatFormatStr); - Args.push_back(Info->Storage); + Args.push_back(Target.Addr); Builder->CreateCall(ScanfFunc, Args); } else if (TypeInfo->isBoolean()) { AllocaInst *TempInt = CreateEntryBlockAlloca(Builder->GetInsertBlock()->getParent(), "tmp_bool_input"); @@ -153,21 +144,21 @@ void CodeGen::emitStmt(StmtAST *Stmt) { Value *Val = Builder->CreateLoad(Type::getInt64Ty(*TheContext), TempInt); Value *BoolVal = Builder->CreateICmpNE(Val, ConstantInt::get(*TheContext, APInt(64, 0)), "bool_cast"); - Builder->CreateStore(BoolVal, Info->Storage); + Builder->CreateStore(BoolVal, Target.Addr); } else if (TypeInfo->isString()) { Value *Mem = Builder->CreateCall(MallocFunc, ConstantInt::get(*TheContext, APInt(64, 1024)), "input_str"); Args.push_back(ScanfStringFormatStr); Args.push_back(Mem); Builder->CreateCall(ScanfFunc, Args); - Builder->CreateStore(Mem, Info->Storage); + Builder->CreateStore(Mem, Target.Addr); } else if (TypeInfo->isChar()) { Value *CharFmt = Builder->CreateGlobalString(" %c", "fmt_in_char", 0, TheModule.get()); Args.push_back(CharFmt); - Args.push_back(Info->Storage); + Args.push_back(Target.Addr); Builder->CreateCall(ScanfFunc, Args); } else if (TypeInfo->Kind == TypeKind::Integer) { Args.push_back(ScanfFormatStr); - Args.push_back(Info->Storage); + Args.push_back(Target.Addr); Builder->CreateCall(ScanfFunc, Args); } else { // Enum/Record/Pointer and any future kind: scanf'ing raw bytes diff --git a/lib/Parser/Parser.cc b/lib/Parser/Parser.cc index f2fcbc8..d4d04d2 100644 --- a/lib/Parser/Parser.cc +++ b/lib/Parser/Parser.cc @@ -116,14 +116,17 @@ std::unique_ptr<StmtAST> Parser::ParseStatementImpl() { std::string Name = Lex.IdentifierStr; int Line = Lex.getLine(); getNextToken(); - if (CurTok == '[' || CurTok == '.' || CurTok == '^') { - // Consume the whole designator so it cannot replay as statements. - std::vector<DesignatorAccess> Dummy; - ParseDesignatorSuffix(Dummy); - fprintf(stderr, "error: INPUT target must be a plain variable at line %d\n", Line); - return nullptr; - } - return std::make_unique<InputStmtAST>(Name); + std::vector<DesignatorAccess> Accesses; + if (!ParseDesignatorSuffix(Accesses)) return nullptr; + std::unique_ptr<ExprAST> Target; + if (Accesses.empty()) + Target = std::make_unique<VariableExprAST>(Name); + else if (Accesses.size() == 1 && Accesses[0].Kind == AccessKind::Index) + Target = std::make_unique<ArrayAccessExprAST>(Name, std::move(Accesses[0].Indices), Line); + else + Target = std::make_unique<DesignatorExprAST>(Name, std::move(Accesses), Line); + Target->setLine(Line); + return std::make_unique<InputStmtAST>(std::move(Target)); } else if (CurTok == tok_output) { getNextToken(); |
