From a8612da85b9c9fc985341d95de1cfe8ed535913b Mon Sep 17 00:00:00 2001 From: Alex Cameron Date: Sat, 24 Oct 2026 23:50:37 +1100 Subject: [PATCH] fix(translate): reject redefinition of a word with a diagnostic Fixes #118 --- lib/Translation/ForthToMLIR/ForthToMLIR.cpp | 9 ++++++++- lib/Translation/ForthToMLIR/ForthToMLIR.h | 3 +-- test/Translation/Forth/word-redefinition-error.forth | 9 +++++++++ 3 files changed, 18 insertions(+), 3 deletions(-) create mode 100644 test/Translation/Forth/word-redefinition-error.forth diff --git a/lib/Translation/ForthToMLIR/ForthToMLIR.cpp b/lib/Translation/ForthToMLIR/ForthToMLIR.cpp index aa9f726..6e94a40 100644 --- a/lib/Translation/ForthToMLIR/ForthToMLIR.cpp +++ b/lib/Translation/ForthToMLIR/ForthToMLIR.cpp @@ -1405,6 +1405,13 @@ LogicalResult ForthParser::parseWordDefinition() { return emitError("kernel name '" + kernelName + "' conflicts with word " + currentToken.text); } + llvm::SMLoc nameLoc = currentToken.location; + if (auto previous = wordDefs.find(wordName); previous != wordDefs.end()) { + (void)emitError("word '" + wordName + "' is already defined"); + sourceMgr.PrintMessage(previous->second, llvm::SourceMgr::DK_Note, + "previous definition is here"); + return failure(); + } consume(); // consume word name // Create function: !forth.stack -> !forth.stack @@ -1435,7 +1442,7 @@ LogicalResult ForthParser::parseWordDefinition() { builder.create(loc, resultStack); // Register the word - wordDefs.insert(wordName); + wordDefs[wordName] = nameLoc; consume(); // consume ';' return success(); diff --git a/lib/Translation/ForthToMLIR/ForthToMLIR.h b/lib/Translation/ForthToMLIR/ForthToMLIR.h index 04317f6..53ee87c 100644 --- a/lib/Translation/ForthToMLIR/ForthToMLIR.h +++ b/lib/Translation/ForthToMLIR/ForthToMLIR.h @@ -12,7 +12,6 @@ #include "llvm/ADT/StringMap.h" #include "llvm/Support/SourceMgr.h" #include -#include #include namespace mlir { @@ -98,7 +97,7 @@ class ForthParser { OpBuilder builder; ForthLexer lexer; Token currentToken; - std::unordered_set wordDefs; + llvm::StringMap wordDefs; std::vector paramDecls; std::vector sharedDecls; llvm::StringMap paramValues; diff --git a/test/Translation/Forth/word-redefinition-error.forth b/test/Translation/Forth/word-redefinition-error.forth new file mode 100644 index 0000000..71cbaeb --- /dev/null +++ b/test/Translation/Forth/word-redefinition-error.forth @@ -0,0 +1,9 @@ +\ RUN: %not %warpforth-translate --forth-to-mlir %s 2>&1 | %FileCheck %s +\ CHECK: :[[@LINE+6]]:3: error: word 'FOO' is already defined +\ CHECK: :[[@LINE+4]]:3: note: previous definition is here +\ CHECK-NOT: redefinition of symbol +\! kernel k +\! param a i64[1] +: foo 1 ; +: foo 2 ; +foo a !