[clang] [MLIR][scf.parallel] Don't allow a tile size of 0 (PR #68762)

Justin Fargnoli via cfe-commits cfe-commits at lists.llvm.org
Sat Oct 21 16:31:36 PDT 2023


https://github.com/justinfargnoli updated https://github.com/llvm/llvm-project/pull/68762

>From d7da0166d78aa30a3f3c66aaa963ff53c166ec90 Mon Sep 17 00:00:00 2001
From: justinfargnoli <justinfargnoli at gmail.com>
Date: Wed, 4 Oct 2023 08:38:40 -0700
Subject: [PATCH 01/16] Add lisp example

---
 mlir/examples/CMakeLists.txt | 1 +
 1 file changed, 1 insertion(+)

diff --git a/mlir/examples/CMakeLists.txt b/mlir/examples/CMakeLists.txt
index d256bf1a5cbb13d..734d5c83abef6cd 100644
--- a/mlir/examples/CMakeLists.txt
+++ b/mlir/examples/CMakeLists.txt
@@ -1,3 +1,4 @@
 add_subdirectory(toy)
 add_subdirectory(transform)
 add_subdirectory(minimal-opt)
+add_subdirectory(lisp)

>From 8ec540ab75a4ed04dfed0021c4279cad217ff262 Mon Sep 17 00:00:00 2001
From: justinfargnoli <justinfargnoli at gmail.com>
Date: Wed, 4 Oct 2023 22:02:17 -0700
Subject: [PATCH 02/16] Saving initial copy of Toy Ch1 as Lisp

---
 mlir/examples/lisp/CMakeLists.txt |  16 +
 mlir/examples/lisp/lisp/AST.h     | 246 +++++++++++++++
 mlir/examples/lisp/lisp/Lexer.h   | 212 +++++++++++++
 mlir/examples/lisp/lisp/Parser.h  | 489 ++++++++++++++++++++++++++++++
 mlir/examples/lisp/lispc.cpp      |  66 ++++
 mlir/examples/lisp/parser/AST.cpp | 234 ++++++++++++++
 6 files changed, 1263 insertions(+)
 create mode 100644 mlir/examples/lisp/CMakeLists.txt
 create mode 100644 mlir/examples/lisp/lisp/AST.h
 create mode 100644 mlir/examples/lisp/lisp/Lexer.h
 create mode 100644 mlir/examples/lisp/lisp/Parser.h
 create mode 100644 mlir/examples/lisp/lispc.cpp
 create mode 100644 mlir/examples/lisp/parser/AST.cpp

diff --git a/mlir/examples/lisp/CMakeLists.txt b/mlir/examples/lisp/CMakeLists.txt
new file mode 100644
index 000000000000000..35bfe7804cbb270
--- /dev/null
+++ b/mlir/examples/lisp/CMakeLists.txt
@@ -0,0 +1,16 @@
+add_custom_target(Lisp)
+set_target_properties(Lisp PROPERTIES FOLDER Examples)
+
+
+add_dependencies(Lisp lispc)
+add_llvm_example(lispc lispc.cpp parser/AST.cpp)
+
+set(LLVM_LINK_COMPONENTS
+  Support
+  )
+
+
+include_directories(include/)
+target_link_libraries(lispc
+  PRIVATE
+    MLIRSupport)
diff --git a/mlir/examples/lisp/lisp/AST.h b/mlir/examples/lisp/lisp/AST.h
new file mode 100644
index 000000000000000..8571b5d9f88c1b2
--- /dev/null
+++ b/mlir/examples/lisp/lisp/AST.h
@@ -0,0 +1,246 @@
+//===- AST.h - Node definition for the Lisp AST ----------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the AST for the Lisp language. It is optimized for
+// simplicity, not efficiency. The AST forms a tree structure where each node
+// references its children using std::unique_ptr<>.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LISP_AST_H
+#define LISP_AST_H
+
+#include "lisp/Lexer.h"
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Casting.h"
+#include <utility>
+#include <vector>
+#include <optional>
+
+namespace lisp {
+
+/// A variable type with shape information.
+struct VarType {
+  std::vector<int64_t> shape;
+};
+
+/// Base class for all expression nodes.
+class ExprAST {
+public:
+  enum ExprASTKind {
+    Expr_VarDecl,
+    Expr_Return,
+    Expr_Num,
+    Expr_Literal,
+    Expr_Var,
+    Expr_BinOp,
+    Expr_Call,
+    Expr_Print,
+  };
+
+  ExprAST(ExprASTKind kind, Location location)
+      : kind(kind), location(std::move(location)) {}
+  virtual ~ExprAST() = default;
+
+  ExprASTKind getKind() const { return kind; }
+
+  const Location &loc() { return location; }
+
+private:
+  const ExprASTKind kind;
+  Location location;
+};
+
+/// A block-list of expressions.
+using ExprASTList = std::vector<std::unique_ptr<ExprAST>>;
+
+/// Expression class for numeric literals like "1.0".
+class NumberExprAST : public ExprAST {
+  double val;
+
+public:
+  NumberExprAST(Location loc, double val)
+      : ExprAST(Expr_Num, std::move(loc)), val(val) {}
+
+  double getValue() { return val; }
+
+  /// LLVM style RTTI
+  static bool classof(const ExprAST *c) { return c->getKind() == Expr_Num; }
+};
+
+/// Expression class for a literal value.
+class LiteralExprAST : public ExprAST {
+  std::vector<std::unique_ptr<ExprAST>> values;
+  std::vector<int64_t> dims;
+
+public:
+  LiteralExprAST(Location loc, std::vector<std::unique_ptr<ExprAST>> values,
+                 std::vector<int64_t> dims)
+      : ExprAST(Expr_Literal, std::move(loc)), values(std::move(values)),
+        dims(std::move(dims)) {}
+
+  llvm::ArrayRef<std::unique_ptr<ExprAST>> getValues() { return values; }
+  llvm::ArrayRef<int64_t> getDims() { return dims; }
+
+  /// LLVM style RTTI
+  static bool classof(const ExprAST *c) { return c->getKind() == Expr_Literal; }
+};
+
+/// Expression class for referencing a variable, like "a".
+class VariableExprAST : public ExprAST {
+  std::string name;
+
+public:
+  VariableExprAST(Location loc, llvm::StringRef name)
+      : ExprAST(Expr_Var, std::move(loc)), name(name) {}
+
+  llvm::StringRef getName() { return name; }
+
+  /// LLVM style RTTI
+  static bool classof(const ExprAST *c) { return c->getKind() == Expr_Var; }
+};
+
+/// Expression class for defining a variable.
+class VarDeclExprAST : public ExprAST {
+  std::string name;
+  VarType type;
+  std::unique_ptr<ExprAST> initVal;
+
+public:
+  VarDeclExprAST(Location loc, llvm::StringRef name, VarType type,
+                 std::unique_ptr<ExprAST> initVal)
+      : ExprAST(Expr_VarDecl, std::move(loc)), name(name),
+        type(std::move(type)), initVal(std::move(initVal)) {}
+
+  llvm::StringRef getName() { return name; }
+  ExprAST *getInitVal() { return initVal.get(); }
+  const VarType &getType() { return type; }
+
+  /// LLVM style RTTI
+  static bool classof(const ExprAST *c) { return c->getKind() == Expr_VarDecl; }
+};
+
+/// Expression class for a return operator.
+class ReturnExprAST : public ExprAST {
+  std::optional<std::unique_ptr<ExprAST>> expr;
+
+public:
+  ReturnExprAST(Location loc, std::optional<std::unique_ptr<ExprAST>> expr)
+      : ExprAST(Expr_Return, std::move(loc)), expr(std::move(expr)) {}
+
+  std::optional<ExprAST *> getExpr() {
+    if (expr.has_value())
+      return expr->get();
+    return std::nullopt;
+  }
+
+  /// LLVM style RTTI
+  static bool classof(const ExprAST *c) { return c->getKind() == Expr_Return; }
+};
+
+/// Expression class for a binary operator.
+class BinaryExprAST : public ExprAST {
+  char op;
+  std::unique_ptr<ExprAST> lhs, rhs;
+
+public:
+  char getOp() { return op; }
+  ExprAST *getLHS() { return lhs.get(); }
+  ExprAST *getRHS() { return rhs.get(); }
+
+  BinaryExprAST(Location loc, char op, std::unique_ptr<ExprAST> lhs,
+                std::unique_ptr<ExprAST> rhs)
+      : ExprAST(Expr_BinOp, std::move(loc)), op(op), lhs(std::move(lhs)),
+        rhs(std::move(rhs)) {}
+
+  /// LLVM style RTTI
+  static bool classof(const ExprAST *c) { return c->getKind() == Expr_BinOp; }
+};
+
+/// Expression class for function calls.
+class CallExprAST : public ExprAST {
+  std::string callee;
+  std::vector<std::unique_ptr<ExprAST>> args;
+
+public:
+  CallExprAST(Location loc, const std::string &callee,
+              std::vector<std::unique_ptr<ExprAST>> args)
+      : ExprAST(Expr_Call, std::move(loc)), callee(callee),
+        args(std::move(args)) {}
+
+  llvm::StringRef getCallee() { return callee; }
+  llvm::ArrayRef<std::unique_ptr<ExprAST>> getArgs() { return args; }
+
+  /// LLVM style RTTI
+  static bool classof(const ExprAST *c) { return c->getKind() == Expr_Call; }
+};
+
+/// Expression class for builtin print calls.
+class PrintExprAST : public ExprAST {
+  std::unique_ptr<ExprAST> arg;
+
+public:
+  PrintExprAST(Location loc, std::unique_ptr<ExprAST> arg)
+      : ExprAST(Expr_Print, std::move(loc)), arg(std::move(arg)) {}
+
+  ExprAST *getArg() { return arg.get(); }
+
+  /// LLVM style RTTI
+  static bool classof(const ExprAST *c) { return c->getKind() == Expr_Print; }
+};
+
+/// This class represents the "prototype" for a function, which captures its
+/// name, and its argument names (thus implicitly the number of arguments the
+/// function takes).
+class PrototypeAST {
+  Location location;
+  std::string name;
+  std::vector<std::unique_ptr<VariableExprAST>> args;
+
+public:
+  PrototypeAST(Location location, const std::string &name,
+               std::vector<std::unique_ptr<VariableExprAST>> args)
+      : location(std::move(location)), name(name), args(std::move(args)) {}
+
+  const Location &loc() { return location; }
+  llvm::StringRef getName() const { return name; }
+  llvm::ArrayRef<std::unique_ptr<VariableExprAST>> getArgs() { return args; }
+};
+
+/// This class represents a function definition itself.
+class FunctionAST {
+  std::unique_ptr<PrototypeAST> proto;
+  std::unique_ptr<ExprASTList> body;
+
+public:
+  FunctionAST(std::unique_ptr<PrototypeAST> proto,
+              std::unique_ptr<ExprASTList> body)
+      : proto(std::move(proto)), body(std::move(body)) {}
+  PrototypeAST *getProto() { return proto.get(); }
+  ExprASTList *getBody() { return body.get(); }
+};
+
+/// This class represents a list of functions to be processed together
+class ModuleAST {
+  std::vector<FunctionAST> functions;
+
+public:
+  ModuleAST(std::vector<FunctionAST> functions)
+      : functions(std::move(functions)) {}
+
+  auto begin() { return functions.begin(); }
+  auto end() { return functions.end(); }
+};
+
+void dump(ModuleAST &);
+
+} // namespace lisp
+
+#endif // LISP_AST_H
diff --git a/mlir/examples/lisp/lisp/Lexer.h b/mlir/examples/lisp/lisp/Lexer.h
new file mode 100644
index 000000000000000..5b06bbc76ce3c94
--- /dev/null
+++ b/mlir/examples/lisp/lisp/Lexer.h
@@ -0,0 +1,212 @@
+//===- Lexer.h - Lexer for the Lisp language -------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements a simple Lexer for the Lisp language.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LISP_LEXER_H
+#define LISP_LEXER_H
+
+#include "llvm/ADT/StringRef.h"
+
+#include <memory>
+#include <string>
+
+namespace lisp {
+
+/// Structure definition a location in a file.
+struct Location {
+  std::shared_ptr<std::string> file; ///< filename.
+  int line;                          ///< line number.
+  int col;                           ///< column number.
+};
+
+// List of Token returned by the lexer.
+enum Token : int {
+  tok_parenthese_open = '(',
+  tok_parenthese_close = ')',
+  tok_eof = -1,
+  tok_number = -2,
+  tok_identifier = -3
+};
+
+/// The Lexer is an abstract base class providing all the facilities that the
+/// Parser expects. It goes through the stream one token at a time and keeps
+/// track of the location in the file for debugging purposes.
+/// It relies on a subclass to provide a `readNextLine()` method. The subclass
+/// can proceed by reading the next line from the standard input or from a
+/// memory mapped file.
+class Lexer {
+public:
+  /// Create a lexer for the given filename. The filename is kept only for
+  /// debugging purposes (attaching a location to a Token).
+  Lexer(std::string filename)
+      : lastLocation(
+            {std::make_shared<std::string>(std::move(filename)), 0, 0}) {}
+  virtual ~Lexer() = default;
+
+  /// Look at the current token in the stream.
+  Token getCurToken() { return curTok; }
+
+  /// Move to the next token in the stream and return it.
+  Token getNextToken() { return curTok = getTok(); }
+
+  /// Move to the next token in the stream, asserting on the current token
+  /// matching the expectation.
+  void consume(Token tok) {
+    assert(tok == curTok && "consume Token mismatch expectation");
+    getNextToken();
+  }
+
+  /// Return the current identifier (prereq: getCurToken() == tok_identifier)
+  llvm::StringRef getId() {
+    assert(curTok == tok_identifier);
+    return identifierStr;
+  }
+
+  /// Return the current number (prereq: getCurToken() == tok_number)
+  double getValue() {
+    assert(curTok == tok_number);
+    return numVal;
+  }
+
+  /// Return the location for the beginning of the current token.
+  Location getLastLocation() { return lastLocation; }
+
+  // Return the current line in the file.
+  int getLine() { return curLineNum; }
+
+  // Return the current column in the file.
+  int getCol() { return curCol; }
+
+private:
+  /// Delegate to a derived class fetching the next line. Returns an empty
+  /// string to signal end of file (EOF). Lines are expected to always finish
+  /// with "\n"
+  virtual llvm::StringRef readNextLine() = 0;
+
+  /// Return the next character from the stream. This manages the buffer for the
+  /// current line and request the next line buffer to the derived class as
+  /// needed.
+  int getNextChar() {
+    // The current line buffer should not be empty unless it is the end of file.
+    if (curLineBuffer.empty())
+      return EOF;
+    ++curCol;
+    auto nextchar = curLineBuffer.front();
+    curLineBuffer = curLineBuffer.drop_front();
+    if (curLineBuffer.empty())
+      curLineBuffer = readNextLine();
+    if (nextchar == '\n') {
+      ++curLineNum;
+      curCol = 0;
+    }
+    return nextchar;
+  }
+
+  ///  Return the next token from standard input.
+  Token getTok() {
+    // Skip any whitespace.
+    while (isspace(lastChar))
+      lastChar = Token(getNextChar());
+
+    // Save the current location before reading the token characters.
+    lastLocation.line = curLineNum;
+    lastLocation.col = curCol;
+
+    // Identifier: [a-zA-Z][a-zA-Z0-9_]*
+    if (isalpha(lastChar)) {
+      identifierStr = (char)lastChar;
+      while (isalnum((lastChar = Token(getNextChar()))) || lastChar == '_')
+        identifierStr += (char)lastChar;
+      return tok_identifier;
+    }
+
+    // Number: [0-9.]+
+    if (isdigit(lastChar) || lastChar == '.') {
+      std::string numStr;
+      do {
+        numStr += lastChar;
+        lastChar = Token(getNextChar());
+      } while (isdigit(lastChar) || lastChar == '.');
+
+      numVal = strtod(numStr.c_str(), nullptr);
+      return tok_number;
+    }
+
+    if (lastChar == '#') {
+      // Comment until end of line.
+      do {
+        lastChar = Token(getNextChar());
+      } while (lastChar != EOF && lastChar != '\n' && lastChar != '\r');
+
+      if (lastChar != EOF)
+        return getTok();
+    }
+
+    // Check for end of file.  Don't eat the EOF.
+    if (lastChar == EOF)
+      return tok_eof;
+
+    // Otherwise, just return the character as its ascii value.
+    Token thisChar = Token(lastChar);
+    lastChar = Token(getNextChar());
+    return thisChar;
+  }
+
+  /// The last token read from the input.
+  Token curTok = tok_eof;
+
+  /// Location for `curTok`.
+  Location lastLocation;
+
+  /// If the current Token is an identifier, this string contains the value.
+  std::string identifierStr;
+
+  /// If the current Token is a number, this contains the value.
+  double numVal = 0;
+
+  /// The last value returned by getNextChar(). We need to keep it around as we
+  /// always need to read ahead one character to decide when to end a token and
+  /// we can't put it back in the stream after reading from it.
+  Token lastChar = Token(' ');
+
+  /// Keep track of the current line number in the input stream
+  int curLineNum = 0;
+
+  /// Keep track of the current column number in the input stream
+  int curCol = 0;
+
+  /// Buffer supplied by the derived class on calls to `readNextLine()`
+  llvm::StringRef curLineBuffer = "\n";
+};
+
+/// A lexer implementation operating on a buffer in memory.
+class LexerBuffer final : public Lexer {
+public:
+  LexerBuffer(const char *begin, const char *end, std::string filename)
+      : Lexer(std::move(filename)), current(begin), end(end) {}
+
+private:
+  /// Provide one line at a time to the Lexer, return an empty string when
+  /// reaching the end of the buffer.
+  llvm::StringRef readNextLine() override {
+    auto *begin = current;
+    while (current <= end && *current && *current != '\n')
+      ++current;
+    if (current <= end && *current)
+      ++current;
+    llvm::StringRef result{begin, static_cast<size_t>(current - begin)};
+    return result;
+  }
+  const char *current, *end;
+};
+} // namespace lisp
+
+#endif // LISP_LEXER_H
diff --git a/mlir/examples/lisp/lisp/Parser.h b/mlir/examples/lisp/lisp/Parser.h
new file mode 100644
index 000000000000000..5cd884e686aa992
--- /dev/null
+++ b/mlir/examples/lisp/lisp/Parser.h
@@ -0,0 +1,489 @@
+//===- Parser.h - Toy Language Parser -------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the parser for the Toy language. It processes the Token
+// provided by the Lexer and returns an AST.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef TOY_PARSER_H
+#define TOY_PARSER_H
+
+#include "lisp/AST.h"
+#include "lisp/Lexer.h"
+
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/Support/raw_ostream.h"
+
+#include <map>
+#include <utility>
+#include <vector>
+#include <optional>
+
+namespace lisp {
+
+/// This is a simple recursive parser for the Toy language. It produces a well
+/// formed AST from a stream of Token supplied by the Lexer. No semantic checks
+/// or symbol resolution is performed. For example, variables are referenced by
+/// string and the code could reference an undeclared variable and the parsing
+/// succeeds.
+class Parser {
+public:
+  /// Create a Parser for the supplied lexer.
+  Parser(Lexer &lexer) : lexer(lexer) {}
+
+  /// Parse a full Module. A module is a list of function definitions.
+  std::unique_ptr<ModuleAST> parseModule() {
+    lexer.getNextToken(); // prime the lexer
+
+    // Parse functions one at a time and accumulate in this vector.
+    std::vector<FunctionAST> functions;
+    while (auto f = parseDefinition()) {
+      functions.push_back(std::move(*f));
+      if (lexer.getCurToken() == tok_eof)
+        break;
+    }
+    // If we didn't reach EOF, there was an error during parsing
+    if (lexer.getCurToken() != tok_eof)
+      return parseError<ModuleAST>("nothing", "at end of module");
+
+    return std::make_unique<ModuleAST>(std::move(functions));
+  }
+
+private:
+  Lexer &lexer;
+
+  /// Parse a return statement.
+  /// return :== return ; | return expr ;
+  std::unique_ptr<ReturnExprAST> parseReturn() {
+    auto loc = lexer.getLastLocation();
+    lexer.consume(tok_return);
+
+    // return takes an optional argument
+    std::optional<std::unique_ptr<ExprAST>> expr;
+    if (lexer.getCurToken() != ';') {
+      expr = parseExpression();
+      if (!expr)
+        return nullptr;
+    }
+    return std::make_unique<ReturnExprAST>(std::move(loc), std::move(expr));
+  }
+
+  /// Parse a literal number.
+  /// numberexpr ::= number
+  std::unique_ptr<ExprAST> parseNumberExpr() {
+    auto loc = lexer.getLastLocation();
+    auto result =
+        std::make_unique<NumberExprAST>(std::move(loc), lexer.getValue());
+    lexer.consume(tok_number);
+    return std::move(result);
+  }
+
+  /// Parse a literal array expression.
+  /// tensorLiteral ::= [ literalList ] | number
+  /// literalList ::= tensorLiteral | tensorLiteral, literalList
+  std::unique_ptr<ExprAST> parseTensorLiteralExpr() {
+    auto loc = lexer.getLastLocation();
+    lexer.consume(Token('['));
+
+    // Hold the list of values at this nesting level.
+    std::vector<std::unique_ptr<ExprAST>> values;
+    // Hold the dimensions for all the nesting inside this level.
+    std::vector<int64_t> dims;
+    do {
+      // We can have either another nested array or a number literal.
+      if (lexer.getCurToken() == '[') {
+        values.push_back(parseTensorLiteralExpr());
+        if (!values.back())
+          return nullptr; // parse error in the nested array.
+      } else {
+        if (lexer.getCurToken() != tok_number)
+          return parseError<ExprAST>("<num> or [", "in literal expression");
+        values.push_back(parseNumberExpr());
+      }
+
+      // End of this list on ']'
+      if (lexer.getCurToken() == ']')
+        break;
+
+      // Elements are separated by a comma.
+      if (lexer.getCurToken() != ',')
+        return parseError<ExprAST>("] or ,", "in literal expression");
+
+      lexer.getNextToken(); // eat ,
+    } while (true);
+    if (values.empty())
+      return parseError<ExprAST>("<something>", "to fill literal expression");
+    lexer.getNextToken(); // eat ]
+
+    /// Fill in the dimensions now. First the current nesting level:
+    dims.push_back(values.size());
+
+    /// If there is any nested array, process all of them and ensure that
+    /// dimensions are uniform.
+    if (llvm::any_of(values, [](std::unique_ptr<ExprAST> &expr) {
+          return llvm::isa<LiteralExprAST>(expr.get());
+        })) {
+      auto *firstLiteral = llvm::dyn_cast<LiteralExprAST>(values.front().get());
+      if (!firstLiteral)
+        return parseError<ExprAST>("uniform well-nested dimensions",
+                                   "inside literal expression");
+
+      // Append the nested dimensions to the current level
+      auto firstDims = firstLiteral->getDims();
+      dims.insert(dims.end(), firstDims.begin(), firstDims.end());
+
+      // Sanity check that shape is uniform across all elements of the list.
+      for (auto &expr : values) {
+        auto *exprLiteral = llvm::cast<LiteralExprAST>(expr.get());
+        if (!exprLiteral)
+          return parseError<ExprAST>("uniform well-nested dimensions",
+                                     "inside literal expression");
+        if (exprLiteral->getDims() != firstDims)
+          return parseError<ExprAST>("uniform well-nested dimensions",
+                                     "inside literal expression");
+      }
+    }
+    return std::make_unique<LiteralExprAST>(std::move(loc), std::move(values),
+                                            std::move(dims));
+  }
+
+  /// parenexpr ::= '(' expression ')'
+  std::unique_ptr<ExprAST> parseParenExpr() {
+    lexer.getNextToken(); // eat (.
+    auto v = parseExpression();
+    if (!v)
+      return nullptr;
+
+    if (lexer.getCurToken() != ')')
+      return parseError<ExprAST>(")", "to close expression with parentheses");
+    lexer.consume(Token(')'));
+    return v;
+  }
+
+  /// identifierexpr
+  ///   ::= identifier
+  ///   ::= identifier '(' expression ')'
+  std::unique_ptr<ExprAST> parseIdentifierExpr() {
+    std::string name(lexer.getId());
+
+    auto loc = lexer.getLastLocation();
+    lexer.getNextToken(); // eat identifier.
+
+    if (lexer.getCurToken() != '(') // Simple variable ref.
+      return std::make_unique<VariableExprAST>(std::move(loc), name);
+
+    // This is a function call.
+    lexer.consume(Token('('));
+    std::vector<std::unique_ptr<ExprAST>> args;
+    if (lexer.getCurToken() != ')') {
+      while (true) {
+        if (auto arg = parseExpression())
+          args.push_back(std::move(arg));
+        else
+          return nullptr;
+
+        if (lexer.getCurToken() == ')')
+          break;
+
+        if (lexer.getCurToken() != ',')
+          return parseError<ExprAST>(", or )", "in argument list");
+        lexer.getNextToken();
+      }
+    }
+    lexer.consume(Token(')'));
+
+    // It can be a builtin call to print
+    if (name == "print") {
+      if (args.size() != 1)
+        return parseError<ExprAST>("<single arg>", "as argument to print()");
+
+      return std::make_unique<PrintExprAST>(std::move(loc), std::move(args[0]));
+    }
+
+    // Call to a user-defined function
+    return std::make_unique<CallExprAST>(std::move(loc), name, std::move(args));
+  }
+
+  /// primary
+  ///   ::= identifierexpr
+  ///   ::= numberexpr
+  ///   ::= parenexpr
+  ///   ::= tensorliteral
+  std::unique_ptr<ExprAST> parsePrimary() {
+    switch (lexer.getCurToken()) {
+    default:
+      llvm::errs() << "unknown token '" << lexer.getCurToken()
+                   << "' when expecting an expression\n";
+      return nullptr;
+    case tok_identifier:
+      return parseIdentifierExpr();
+    case tok_number:
+      return parseNumberExpr();
+    case '(':
+      return parseParenExpr();
+    case '[':
+      return parseTensorLiteralExpr();
+    case ';':
+      return nullptr;
+    case '}':
+      return nullptr;
+    }
+  }
+
+  /// Recursively parse the right hand side of a binary expression, the ExprPrec
+  /// argument indicates the precedence of the current binary operator.
+  ///
+  /// binoprhs ::= ('+' primary)*
+  std::unique_ptr<ExprAST> parseBinOpRHS(int exprPrec,
+                                         std::unique_ptr<ExprAST> lhs) {
+    // If this is a binop, find its precedence.
+    while (true) {
+      int tokPrec = getTokPrecedence();
+
+      // If this is a binop that binds at least as tightly as the current binop,
+      // consume it, otherwise we are done.
+      if (tokPrec < exprPrec)
+        return lhs;
+
+      // Okay, we know this is a binop.
+      int binOp = lexer.getCurToken();
+      lexer.consume(Token(binOp));
+      auto loc = lexer.getLastLocation();
+
+      // Parse the primary expression after the binary operator.
+      auto rhs = parsePrimary();
+      if (!rhs)
+        return parseError<ExprAST>("expression", "to complete binary operator");
+
+      // If BinOp binds less tightly with rhs than the operator after rhs, let
+      // the pending operator take rhs as its lhs.
+      int nextPrec = getTokPrecedence();
+      if (tokPrec < nextPrec) {
+        rhs = parseBinOpRHS(tokPrec + 1, std::move(rhs));
+        if (!rhs)
+          return nullptr;
+      }
+
+      // Merge lhs/RHS.
+      lhs = std::make_unique<BinaryExprAST>(std::move(loc), binOp,
+                                            std::move(lhs), std::move(rhs));
+    }
+  }
+
+  /// expression::= primary binop rhs
+  std::unique_ptr<ExprAST> parseExpression() {
+    auto lhs = parsePrimary();
+    if (!lhs)
+      return nullptr;
+
+    return parseBinOpRHS(0, std::move(lhs));
+  }
+
+  /// type ::= < shape_list >
+  /// shape_list ::= num | num , shape_list
+  std::unique_ptr<VarType> parseType() {
+    if (lexer.getCurToken() != '<')
+      return parseError<VarType>("<", "to begin type");
+    lexer.getNextToken(); // eat <
+
+    auto type = std::make_unique<VarType>();
+
+    while (lexer.getCurToken() == tok_number) {
+      type->shape.push_back(lexer.getValue());
+      lexer.getNextToken();
+      if (lexer.getCurToken() == ',')
+        lexer.getNextToken();
+    }
+
+    if (lexer.getCurToken() != '>')
+      return parseError<VarType>(">", "to end type");
+    lexer.getNextToken(); // eat >
+    return type;
+  }
+
+  /// Parse a variable declaration, it starts with a `var` keyword followed by
+  /// and identifier and an optional type (shape specification) before the
+  /// initializer.
+  /// decl ::= var identifier [ type ] = expr
+  std::unique_ptr<VarDeclExprAST> parseDeclaration() {
+    if (lexer.getCurToken() != tok_var)
+      return parseError<VarDeclExprAST>("var", "to begin declaration");
+    auto loc = lexer.getLastLocation();
+    lexer.getNextToken(); // eat var
+
+    if (lexer.getCurToken() != tok_identifier)
+      return parseError<VarDeclExprAST>("identified",
+                                        "after 'var' declaration");
+    std::string id(lexer.getId());
+    lexer.getNextToken(); // eat id
+
+    std::unique_ptr<VarType> type; // Type is optional, it can be inferred
+    if (lexer.getCurToken() == '<') {
+      type = parseType();
+      if (!type)
+        return nullptr;
+    }
+
+    if (!type)
+      type = std::make_unique<VarType>();
+    lexer.consume(Token('='));
+    auto expr = parseExpression();
+    return std::make_unique<VarDeclExprAST>(std::move(loc), std::move(id),
+                                            std::move(*type), std::move(expr));
+  }
+
+  /// Parse a block: a list of expression separated by semicolons and wrapped in
+  /// curly braces.
+  ///
+  /// block ::= { expression_list }
+  /// expression_list ::= block_expr ; expression_list
+  /// block_expr ::= decl | "return" | expr
+  std::unique_ptr<ExprASTList> parseBlock() {
+    if (lexer.getCurToken() != '{')
+      return parseError<ExprASTList>("{", "to begin block");
+    lexer.consume(Token('{'));
+
+    auto exprList = std::make_unique<ExprASTList>();
+
+    // Ignore empty expressions: swallow sequences of semicolons.
+    while (lexer.getCurToken() == ';')
+      lexer.consume(Token(';'));
+
+    while (lexer.getCurToken() != '}' && lexer.getCurToken() != tok_eof) {
+      if (lexer.getCurToken() == tok_var) {
+        // Variable declaration
+        auto varDecl = parseDeclaration();
+        if (!varDecl)
+          return nullptr;
+        exprList->push_back(std::move(varDecl));
+      } else if (lexer.getCurToken() == tok_return) {
+        // Return statement
+        auto ret = parseReturn();
+        if (!ret)
+          return nullptr;
+        exprList->push_back(std::move(ret));
+      } else {
+        // General expression
+        auto expr = parseExpression();
+        if (!expr)
+          return nullptr;
+        exprList->push_back(std::move(expr));
+      }
+      // Ensure that elements are separated by a semicolon.
+      if (lexer.getCurToken() != ';')
+        return parseError<ExprASTList>(";", "after expression");
+
+      // Ignore empty expressions: swallow sequences of semicolons.
+      while (lexer.getCurToken() == ';')
+        lexer.consume(Token(';'));
+    }
+
+    if (lexer.getCurToken() != '}')
+      return parseError<ExprASTList>("}", "to close block");
+
+    lexer.consume(Token('}'));
+    return exprList;
+  }
+
+  /// prototype ::= def id '(' decl_list ')'
+  /// decl_list ::= identifier | identifier, decl_list
+  std::unique_ptr<PrototypeAST> parsePrototype() {
+    auto loc = lexer.getLastLocation();
+
+    if (lexer.getCurToken() != tok_def)
+      return parseError<PrototypeAST>("def", "in prototype");
+    lexer.consume(tok_def);
+
+    if (lexer.getCurToken() != tok_identifier)
+      return parseError<PrototypeAST>("function name", "in prototype");
+
+    std::string fnName(lexer.getId());
+    lexer.consume(tok_identifier);
+
+    if (lexer.getCurToken() != '(')
+      return parseError<PrototypeAST>("(", "in prototype");
+    lexer.consume(Token('('));
+
+    std::vector<std::unique_ptr<VariableExprAST>> args;
+    if (lexer.getCurToken() != ')') {
+      do {
+        std::string name(lexer.getId());
+        auto loc = lexer.getLastLocation();
+        lexer.consume(tok_identifier);
+        auto decl = std::make_unique<VariableExprAST>(std::move(loc), name);
+        args.push_back(std::move(decl));
+        if (lexer.getCurToken() != ',')
+          break;
+        lexer.consume(Token(','));
+        if (lexer.getCurToken() != tok_identifier)
+          return parseError<PrototypeAST>(
+              "identifier", "after ',' in function parameter list");
+      } while (true);
+    }
+    if (lexer.getCurToken() != ')')
+      return parseError<PrototypeAST>(")", "to end function prototype");
+
+    // success.
+    lexer.consume(Token(')'));
+    return std::make_unique<PrototypeAST>(std::move(loc), fnName,
+                                          std::move(args));
+  }
+
+  /// Parse a function definition, we expect a prototype initiated with the
+  /// `def` keyword, followed by a block containing a list of expressions.
+  ///
+  /// definition ::= prototype block
+  std::unique_ptr<FunctionAST> parseDefinition() {
+    auto proto = parsePrototype();
+    if (!proto)
+      return nullptr;
+
+    if (auto block = parseBlock())
+      return std::make_unique<FunctionAST>(std::move(proto), std::move(block));
+    return nullptr;
+  }
+
+  /// Get the precedence of the pending binary operator token.
+  int getTokPrecedence() {
+    if (!isascii(lexer.getCurToken()))
+      return -1;
+
+    // 1 is lowest precedence.
+    switch (static_cast<char>(lexer.getCurToken())) {
+    case '-':
+      return 20;
+    case '+':
+      return 20;
+    case '*':
+      return 40;
+    default:
+      return -1;
+    }
+  }
+
+  /// Helper function to signal errors while parsing, it takes an argument
+  /// indicating the expected token and another argument giving more context.
+  /// Location is retrieved from the lexer to enrich the error message.
+  template <typename R, typename T, typename U = const char *>
+  std::unique_ptr<R> parseError(T &&expected, U &&context = "") {
+    auto curToken = lexer.getCurToken();
+    llvm::errs() << "Parse error (" << lexer.getLastLocation().line << ", "
+                 << lexer.getLastLocation().col << "): expected '" << expected
+                 << "' " << context << " but has Token " << curToken;
+    if (isprint(curToken))
+      llvm::errs() << " '" << (char)curToken << "'";
+    llvm::errs() << "\n";
+    return nullptr;
+  }
+};
+
+} // namespace toy
+
+#endif // TOY_PARSER_H
diff --git a/mlir/examples/lisp/lispc.cpp b/mlir/examples/lisp/lispc.cpp
new file mode 100644
index 000000000000000..9f9920224a5296d
--- /dev/null
+++ b/mlir/examples/lisp/lispc.cpp
@@ -0,0 +1,66 @@
+//===- lispc.cpp - The Lisp Compiler ----------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the entry point for the Lisp compiler.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lisp/Parser.h"
+
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/ErrorOr.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace lisp;
+namespace cl = llvm::cl;
+
+static cl::opt<std::string> inputFilename(cl::Positional,
+                                          cl::desc("<input lisp file>"),
+                                          cl::init("-"),
+                                          cl::value_desc("filename"));
+namespace {
+enum Action { None, DumpAST };
+} // namespace
+
+static cl::opt<enum Action>
+    emitAction("emit", cl::desc("Select the kind of output desired"),
+               cl::values(clEnumValN(DumpAST, "ast", "output the AST dump")));
+
+/// Returns a Lisp AST resulting from parsing the file or a nullptr on error.
+std::unique_ptr<lisp::ModuleAST> parseInputFile(llvm::StringRef filename) {
+  llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> fileOrErr =
+      llvm::MemoryBuffer::getFileOrSTDIN(filename);
+  if (std::error_code ec = fileOrErr.getError()) {
+    llvm::errs() << "Could not open input file: " << ec.message() << "\n";
+    return nullptr;
+  }
+  auto buffer = fileOrErr.get()->getBuffer();
+  LexerBuffer lexer(buffer.begin(), buffer.end(), std::string(filename));
+  Parser parser(lexer);
+  return parser.parseModule();
+}
+
+int main(int argc, char **argv) {
+  cl::ParseCommandLineOptions(argc, argv, "lisp compiler\n");
+
+  auto moduleAST = parseInputFile(inputFilename);
+  if (!moduleAST)
+    return 1;
+
+  switch (emitAction) {
+  case Action::DumpAST:
+    dump(*moduleAST);
+    return 0;
+  default:
+    llvm::errs() << "No action specified (parsing only?), use -emit=<action>\n";
+  }
+
+  return 0;
+}
diff --git a/mlir/examples/lisp/parser/AST.cpp b/mlir/examples/lisp/parser/AST.cpp
new file mode 100644
index 000000000000000..99bde6b8df5e525
--- /dev/null
+++ b/mlir/examples/lisp/parser/AST.cpp
@@ -0,0 +1,234 @@
+//===- AST.cpp - Helper for printing out the Lisp AST ----------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the AST dump for the Lisp language.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lisp/AST.h"
+
+#include "llvm/ADT/Twine.h"
+#include "llvm/ADT/TypeSwitch.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace lisp;
+
+namespace {
+
+// RAII helper to manage increasing/decreasing the indentation as we traverse
+// the AST
+struct Indent {
+  Indent(int &level) : level(level) { ++level; }
+  ~Indent() { --level; }
+  int &level;
+};
+
+/// Helper class that implement the AST tree traversal and print the nodes along
+/// the way. The only data member is the current indentation level.
+class ASTDumper {
+public:
+  void dump(ModuleAST *node);
+
+private:
+  void dump(const VarType &type);
+  void dump(VarDeclExprAST *varDecl);
+  void dump(ExprAST *expr);
+  void dump(ExprASTList *exprList);
+  void dump(NumberExprAST *num);
+  void dump(LiteralExprAST *node);
+  void dump(VariableExprAST *node);
+  void dump(ReturnExprAST *node);
+  void dump(BinaryExprAST *node);
+  void dump(CallExprAST *node);
+  void dump(PrintExprAST *node);
+  void dump(PrototypeAST *node);
+  void dump(FunctionAST *node);
+
+  // Actually print spaces matching the current indentation level
+  void indent() {
+    for (int i = 0; i < curIndent; i++)
+      llvm::errs() << "  ";
+  }
+  int curIndent = 0;
+};
+
+} // namespace
+
+/// Return a formatted string for the location of any node
+template <typename T>
+static std::string loc(T *node) {
+  const auto &loc = node->loc();
+  return (llvm::Twine("@") + *loc.file + ":" + llvm::Twine(loc.line) + ":" +
+          llvm::Twine(loc.col))
+      .str();
+}
+
+// Helper Macro to bump the indentation level and print the leading spaces for
+// the current indentations
+#define INDENT()                                                               \
+  Indent level_(curIndent);                                                    \
+  indent();
+
+/// Dispatch to a generic expressions to the appropriate subclass using RTTI
+void ASTDumper::dump(ExprAST *expr) {
+  llvm::TypeSwitch<ExprAST *>(expr)
+      .Case<BinaryExprAST, CallExprAST, LiteralExprAST, NumberExprAST,
+            PrintExprAST, ReturnExprAST, VarDeclExprAST, VariableExprAST>(
+          [&](auto *node) { this->dump(node); })
+      .Default([&](ExprAST *) {
+        // No match, fallback to a generic message
+        INDENT();
+        llvm::errs() << "<unknown Expr, kind " << expr->getKind() << ">\n";
+      });
+}
+
+/// A variable declaration is printing the variable name, the type, and then
+/// recurse in the initializer value.
+void ASTDumper::dump(VarDeclExprAST *varDecl) {
+  INDENT();
+  llvm::errs() << "VarDecl " << varDecl->getName();
+  dump(varDecl->getType());
+  llvm::errs() << " " << loc(varDecl) << "\n";
+  dump(varDecl->getInitVal());
+}
+
+/// A "block", or a list of expression
+void ASTDumper::dump(ExprASTList *exprList) {
+  INDENT();
+  llvm::errs() << "Block {\n";
+  for (auto &expr : *exprList)
+    dump(expr.get());
+  indent();
+  llvm::errs() << "} // Block\n";
+}
+
+/// A literal number, just print the value.
+void ASTDumper::dump(NumberExprAST *num) {
+  INDENT();
+  llvm::errs() << num->getValue() << " " << loc(num) << "\n";
+}
+
+/// Helper to print recursively a literal. This handles nested array like:
+///    [ [ 1, 2 ], [ 3, 4 ] ]
+/// We print out such array with the dimensions spelled out at every level:
+///    <2,2>[<2>[ 1, 2 ], <2>[ 3, 4 ] ]
+void printLitHelper(ExprAST *litOrNum) {
+  // Inside a literal expression we can have either a number or another literal
+  if (auto *num = llvm::dyn_cast<NumberExprAST>(litOrNum)) {
+    llvm::errs() << num->getValue();
+    return;
+  }
+  auto *literal = llvm::cast<LiteralExprAST>(litOrNum);
+
+  // Print the dimension for this literal first
+  llvm::errs() << "<";
+  llvm::interleaveComma(literal->getDims(), llvm::errs());
+  llvm::errs() << ">";
+
+  // Now print the content, recursing on every element of the list
+  llvm::errs() << "[ ";
+  llvm::interleaveComma(literal->getValues(), llvm::errs(),
+                        [&](auto &elt) { printLitHelper(elt.get()); });
+  llvm::errs() << "]";
+}
+
+/// Print a literal, see the recursive helper above for the implementation.
+void ASTDumper::dump(LiteralExprAST *node) {
+  INDENT();
+  llvm::errs() << "Literal: ";
+  printLitHelper(node);
+  llvm::errs() << " " << loc(node) << "\n";
+}
+
+/// Print a variable reference (just a name).
+void ASTDumper::dump(VariableExprAST *node) {
+  INDENT();
+  llvm::errs() << "var: " << node->getName() << " " << loc(node) << "\n";
+}
+
+/// Return statement print the return and its (optional) argument.
+void ASTDumper::dump(ReturnExprAST *node) {
+  INDENT();
+  llvm::errs() << "Return\n";
+  if (node->getExpr().has_value())
+    return dump(*node->getExpr());
+  {
+    INDENT();
+    llvm::errs() << "(void)\n";
+  }
+}
+
+/// Print a binary operation, first the operator, then recurse into LHS and RHS.
+void ASTDumper::dump(BinaryExprAST *node) {
+  INDENT();
+  llvm::errs() << "BinOp: " << node->getOp() << " " << loc(node) << "\n";
+  dump(node->getLHS());
+  dump(node->getRHS());
+}
+
+/// Print a call expression, first the callee name and the list of args by
+/// recursing into each individual argument.
+void ASTDumper::dump(CallExprAST *node) {
+  INDENT();
+  llvm::errs() << "Call '" << node->getCallee() << "' [ " << loc(node) << "\n";
+  for (auto &arg : node->getArgs())
+    dump(arg.get());
+  indent();
+  llvm::errs() << "]\n";
+}
+
+/// Print a builtin print call, first the builtin name and then the argument.
+void ASTDumper::dump(PrintExprAST *node) {
+  INDENT();
+  llvm::errs() << "Print [ " << loc(node) << "\n";
+  dump(node->getArg());
+  indent();
+  llvm::errs() << "]\n";
+}
+
+/// Print type: only the shape is printed in between '<' and '>'
+void ASTDumper::dump(const VarType &type) {
+  llvm::errs() << "<";
+  llvm::interleaveComma(type.shape, llvm::errs());
+  llvm::errs() << ">";
+}
+
+/// Print a function prototype, first the function name, and then the list of
+/// parameters names.
+void ASTDumper::dump(PrototypeAST *node) {
+  INDENT();
+  llvm::errs() << "Proto '" << node->getName() << "' " << loc(node) << "\n";
+  indent();
+  llvm::errs() << "Params: [";
+  llvm::interleaveComma(node->getArgs(), llvm::errs(),
+                        [](auto &arg) { llvm::errs() << arg->getName(); });
+  llvm::errs() << "]\n";
+}
+
+/// Print a function, first the prototype and then the body.
+void ASTDumper::dump(FunctionAST *node) {
+  INDENT();
+  llvm::errs() << "Function \n";
+  dump(node->getProto());
+  dump(node->getBody());
+}
+
+/// Print a module, actually loop over the functions and print them in sequence.
+void ASTDumper::dump(ModuleAST *node) {
+  INDENT();
+  llvm::errs() << "Module:\n";
+  for (auto &f : *node)
+    dump(&f);
+}
+
+namespace lisp {
+
+// Public API
+void dump(ModuleAST &module) { ASTDumper().dump(&module); }
+
+} // namespace lisp

>From 71708753642d2ee6f8fdedf2423d573a3165eb67 Mon Sep 17 00:00:00 2001
From: justinfargnoli <justinfargnoli at gmail.com>
Date: Wed, 4 Oct 2023 22:40:10 -0700
Subject: [PATCH 03/16] Fresh copy of Toy Ch1

---
 mlir/examples/CMakeLists.txt                  |  2 +-
 mlir/examples/jus/CMakeLists.txt              | 19 ++++++++++
 .../{lisp/lisp => jus/include/toy}/AST.h      | 16 ++++----
 .../{lisp/lisp => jus/include/toy}/Lexer.h    | 38 ++++++++++++++-----
 .../{lisp/lisp => jus/include/toy}/Parser.h   |  6 +--
 mlir/examples/{lisp => jus}/parser/AST.cpp    | 12 +++---
 .../examples/{lisp/lispc.cpp => jus/toyc.cpp} | 16 ++++----
 mlir/examples/lisp/CMakeLists.txt             | 16 --------
 8 files changed, 74 insertions(+), 51 deletions(-)
 create mode 100644 mlir/examples/jus/CMakeLists.txt
 rename mlir/examples/{lisp/lisp => jus/include/toy}/AST.h (96%)
 rename mlir/examples/{lisp/lisp => jus/include/toy}/Lexer.h (90%)
 rename mlir/examples/{lisp/lisp => jus/include/toy}/Parser.h (99%)
 rename mlir/examples/{lisp => jus}/parser/AST.cpp (96%)
 rename mlir/examples/{lisp/lispc.cpp => jus/toyc.cpp} (78%)
 delete mode 100644 mlir/examples/lisp/CMakeLists.txt

diff --git a/mlir/examples/CMakeLists.txt b/mlir/examples/CMakeLists.txt
index 734d5c83abef6cd..e90ec13db1acf04 100644
--- a/mlir/examples/CMakeLists.txt
+++ b/mlir/examples/CMakeLists.txt
@@ -1,4 +1,4 @@
 add_subdirectory(toy)
 add_subdirectory(transform)
 add_subdirectory(minimal-opt)
-add_subdirectory(lisp)
+add_subdirectory(jus)
diff --git a/mlir/examples/jus/CMakeLists.txt b/mlir/examples/jus/CMakeLists.txt
new file mode 100644
index 000000000000000..eaba0544cc073c3
--- /dev/null
+++ b/mlir/examples/jus/CMakeLists.txt
@@ -0,0 +1,19 @@
+add_custom_target(Jus)
+set_target_properties(Jus PROPERTIES FOLDER Examples)
+
+
+add_dependencies(Jus jusc)
+add_llvm_example(jusc
+  toyc.cpp 
+  parser/AST.cpp
+  )
+
+set(LLVM_LINK_COMPONENTS
+  Support
+  )
+
+
+include_directories(include/)
+target_link_libraries(jusc
+  PRIVATE
+    MLIRSupport)
diff --git a/mlir/examples/lisp/lisp/AST.h b/mlir/examples/jus/include/toy/AST.h
similarity index 96%
rename from mlir/examples/lisp/lisp/AST.h
rename to mlir/examples/jus/include/toy/AST.h
index 8571b5d9f88c1b2..d2ba101dea5a412 100644
--- a/mlir/examples/lisp/lisp/AST.h
+++ b/mlir/examples/jus/include/toy/AST.h
@@ -1,4 +1,4 @@
-//===- AST.h - Node definition for the Lisp AST ----------------------------===//
+//===- AST.h - Node definition for the Toy AST ----------------------------===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
@@ -6,16 +6,16 @@
 //
 //===----------------------------------------------------------------------===//
 //
-// This file implements the AST for the Lisp language. It is optimized for
+// This file implements the AST for the Toy language. It is optimized for
 // simplicity, not efficiency. The AST forms a tree structure where each node
 // references its children using std::unique_ptr<>.
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef LISP_AST_H
-#define LISP_AST_H
+#ifndef TOY_AST_H
+#define TOY_AST_H
 
-#include "lisp/Lexer.h"
+#include "toy/Lexer.h"
 
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/StringRef.h"
@@ -24,7 +24,7 @@
 #include <vector>
 #include <optional>
 
-namespace lisp {
+namespace toy {
 
 /// A variable type with shape information.
 struct VarType {
@@ -241,6 +241,6 @@ class ModuleAST {
 
 void dump(ModuleAST &);
 
-} // namespace lisp
+} // namespace toy
 
-#endif // LISP_AST_H
+#endif // TOY_AST_H
diff --git a/mlir/examples/lisp/lisp/Lexer.h b/mlir/examples/jus/include/toy/Lexer.h
similarity index 90%
rename from mlir/examples/lisp/lisp/Lexer.h
rename to mlir/examples/jus/include/toy/Lexer.h
index 5b06bbc76ce3c94..ecbb3b4e0e5835a 100644
--- a/mlir/examples/lisp/lisp/Lexer.h
+++ b/mlir/examples/jus/include/toy/Lexer.h
@@ -1,4 +1,4 @@
-//===- Lexer.h - Lexer for the Lisp language -------------------------------===//
+//===- Lexer.h - Lexer for the Toy language -------------------------------===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
@@ -6,19 +6,19 @@
 //
 //===----------------------------------------------------------------------===//
 //
-// This file implements a simple Lexer for the Lisp language.
+// This file implements a simple Lexer for the Toy language.
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef LISP_LEXER_H
-#define LISP_LEXER_H
+#ifndef TOY_LEXER_H
+#define TOY_LEXER_H
 
 #include "llvm/ADT/StringRef.h"
 
 #include <memory>
 #include <string>
 
-namespace lisp {
+namespace toy {
 
 /// Structure definition a location in a file.
 struct Location {
@@ -29,11 +29,24 @@ struct Location {
 
 // List of Token returned by the lexer.
 enum Token : int {
+  tok_semicolon = ';',
   tok_parenthese_open = '(',
   tok_parenthese_close = ')',
+  tok_bracket_open = '{',
+  tok_bracket_close = '}',
+  tok_sbracket_open = '[',
+  tok_sbracket_close = ']',
+
   tok_eof = -1,
-  tok_number = -2,
-  tok_identifier = -3
+
+  // commands
+  tok_return = -2,
+  tok_var = -3,
+  tok_def = -4,
+
+  // primary
+  tok_identifier = -5,
+  tok_number = -6,
 };
 
 /// The Lexer is an abstract base class providing all the facilities that the
@@ -125,6 +138,13 @@ class Lexer {
       identifierStr = (char)lastChar;
       while (isalnum((lastChar = Token(getNextChar()))) || lastChar == '_')
         identifierStr += (char)lastChar;
+
+      if (identifierStr == "return")
+        return tok_return;
+      if (identifierStr == "def")
+        return tok_def;
+      if (identifierStr == "var")
+        return tok_var;
       return tok_identifier;
     }
 
@@ -207,6 +227,6 @@ class LexerBuffer final : public Lexer {
   }
   const char *current, *end;
 };
-} // namespace lisp
+} // namespace toy
 
-#endif // LISP_LEXER_H
+#endif // TOY_LEXER_H
diff --git a/mlir/examples/lisp/lisp/Parser.h b/mlir/examples/jus/include/toy/Parser.h
similarity index 99%
rename from mlir/examples/lisp/lisp/Parser.h
rename to mlir/examples/jus/include/toy/Parser.h
index 5cd884e686aa992..1f20616ac6b4e14 100644
--- a/mlir/examples/lisp/lisp/Parser.h
+++ b/mlir/examples/jus/include/toy/Parser.h
@@ -14,8 +14,8 @@
 #ifndef TOY_PARSER_H
 #define TOY_PARSER_H
 
-#include "lisp/AST.h"
-#include "lisp/Lexer.h"
+#include "toy/AST.h"
+#include "toy/Lexer.h"
 
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/StringExtras.h"
@@ -26,7 +26,7 @@
 #include <vector>
 #include <optional>
 
-namespace lisp {
+namespace toy {
 
 /// This is a simple recursive parser for the Toy language. It produces a well
 /// formed AST from a stream of Token supplied by the Lexer. No semantic checks
diff --git a/mlir/examples/lisp/parser/AST.cpp b/mlir/examples/jus/parser/AST.cpp
similarity index 96%
rename from mlir/examples/lisp/parser/AST.cpp
rename to mlir/examples/jus/parser/AST.cpp
index 99bde6b8df5e525..2eaabb1b529e1b8 100644
--- a/mlir/examples/lisp/parser/AST.cpp
+++ b/mlir/examples/jus/parser/AST.cpp
@@ -1,4 +1,4 @@
-//===- AST.cpp - Helper for printing out the Lisp AST ----------------------===//
+//===- AST.cpp - Helper for printing out the Toy AST ----------------------===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
@@ -6,17 +6,17 @@
 //
 //===----------------------------------------------------------------------===//
 //
-// This file implements the AST dump for the Lisp language.
+// This file implements the AST dump for the Toy language.
 //
 //===----------------------------------------------------------------------===//
 
-#include "lisp/AST.h"
+#include "toy/AST.h"
 
 #include "llvm/ADT/Twine.h"
 #include "llvm/ADT/TypeSwitch.h"
 #include "llvm/Support/raw_ostream.h"
 
-using namespace lisp;
+using namespace toy;
 
 namespace {
 
@@ -226,9 +226,9 @@ void ASTDumper::dump(ModuleAST *node) {
     dump(&f);
 }
 
-namespace lisp {
+namespace toy {
 
 // Public API
 void dump(ModuleAST &module) { ASTDumper().dump(&module); }
 
-} // namespace lisp
+} // namespace toy
diff --git a/mlir/examples/lisp/lispc.cpp b/mlir/examples/jus/toyc.cpp
similarity index 78%
rename from mlir/examples/lisp/lispc.cpp
rename to mlir/examples/jus/toyc.cpp
index 9f9920224a5296d..ca2a1a1fa8adfc4 100644
--- a/mlir/examples/lisp/lispc.cpp
+++ b/mlir/examples/jus/toyc.cpp
@@ -1,4 +1,4 @@
-//===- lispc.cpp - The Lisp Compiler ----------------------------------------===//
+//===- toyc.cpp - The Toy Compiler ----------------------------------------===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
@@ -6,11 +6,11 @@
 //
 //===----------------------------------------------------------------------===//
 //
-// This file implements the entry point for the Lisp compiler.
+// This file implements the entry point for the Toy compiler.
 //
 //===----------------------------------------------------------------------===//
 
-#include "lisp/Parser.h"
+#include "toy/Parser.h"
 
 #include "llvm/ADT/StringRef.h"
 #include "llvm/Support/CommandLine.h"
@@ -18,11 +18,11 @@
 #include "llvm/Support/MemoryBuffer.h"
 #include "llvm/Support/raw_ostream.h"
 
-using namespace lisp;
+using namespace toy;
 namespace cl = llvm::cl;
 
 static cl::opt<std::string> inputFilename(cl::Positional,
-                                          cl::desc("<input lisp file>"),
+                                          cl::desc("<input toy file>"),
                                           cl::init("-"),
                                           cl::value_desc("filename"));
 namespace {
@@ -33,8 +33,8 @@ static cl::opt<enum Action>
     emitAction("emit", cl::desc("Select the kind of output desired"),
                cl::values(clEnumValN(DumpAST, "ast", "output the AST dump")));
 
-/// Returns a Lisp AST resulting from parsing the file or a nullptr on error.
-std::unique_ptr<lisp::ModuleAST> parseInputFile(llvm::StringRef filename) {
+/// Returns a Toy AST resulting from parsing the file or a nullptr on error.
+std::unique_ptr<toy::ModuleAST> parseInputFile(llvm::StringRef filename) {
   llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> fileOrErr =
       llvm::MemoryBuffer::getFileOrSTDIN(filename);
   if (std::error_code ec = fileOrErr.getError()) {
@@ -48,7 +48,7 @@ std::unique_ptr<lisp::ModuleAST> parseInputFile(llvm::StringRef filename) {
 }
 
 int main(int argc, char **argv) {
-  cl::ParseCommandLineOptions(argc, argv, "lisp compiler\n");
+  cl::ParseCommandLineOptions(argc, argv, "toy compiler\n");
 
   auto moduleAST = parseInputFile(inputFilename);
   if (!moduleAST)
diff --git a/mlir/examples/lisp/CMakeLists.txt b/mlir/examples/lisp/CMakeLists.txt
deleted file mode 100644
index 35bfe7804cbb270..000000000000000
--- a/mlir/examples/lisp/CMakeLists.txt
+++ /dev/null
@@ -1,16 +0,0 @@
-add_custom_target(Lisp)
-set_target_properties(Lisp PROPERTIES FOLDER Examples)
-
-
-add_dependencies(Lisp lispc)
-add_llvm_example(lispc lispc.cpp parser/AST.cpp)
-
-set(LLVM_LINK_COMPONENTS
-  Support
-  )
-
-
-include_directories(include/)
-target_link_libraries(lispc
-  PRIVATE
-    MLIRSupport)

>From 91e3bce5e91351494771535613e67ff9f9152405 Mon Sep 17 00:00:00 2001
From: justinfargnoli <justinfargnoli at gmail.com>
Date: Wed, 4 Oct 2023 22:40:59 -0700
Subject: [PATCH 04/16] White space changes

---
 mlir/examples/jus/CMakeLists.txt | 2 --
 1 file changed, 2 deletions(-)

diff --git a/mlir/examples/jus/CMakeLists.txt b/mlir/examples/jus/CMakeLists.txt
index eaba0544cc073c3..bc705c5d900df67 100644
--- a/mlir/examples/jus/CMakeLists.txt
+++ b/mlir/examples/jus/CMakeLists.txt
@@ -1,7 +1,6 @@
 add_custom_target(Jus)
 set_target_properties(Jus PROPERTIES FOLDER Examples)
 
-
 add_dependencies(Jus jusc)
 add_llvm_example(jusc
   toyc.cpp 
@@ -12,7 +11,6 @@ set(LLVM_LINK_COMPONENTS
   Support
   )
 
-
 include_directories(include/)
 target_link_libraries(jusc
   PRIVATE

>From c168f778a03c6b5ecc6d6482f3cffd42b8fc7678 Mon Sep 17 00:00:00 2001
From: justinfargnoli <justinfargnoli at gmail.com>
Date: Sun, 8 Oct 2023 20:40:30 -0700
Subject: [PATCH 05/16] Don't Allow a `tileSize` of Zero

---
 mlir/lib/Dialect/SCF/Transforms/ParallelLoopTiling.cpp    | 5 +++--
 .../Dialect/SCF/parallel-loop-tiling-tile-size-check.mlir | 8 ++++++++
 2 files changed, 11 insertions(+), 2 deletions(-)
 create mode 100644 mlir/test/Dialect/SCF/parallel-loop-tiling-tile-size-check.mlir

diff --git a/mlir/lib/Dialect/SCF/Transforms/ParallelLoopTiling.cpp b/mlir/lib/Dialect/SCF/Transforms/ParallelLoopTiling.cpp
index 1e04261e2eb3649..7e0e07670ef5221 100644
--- a/mlir/lib/Dialect/SCF/Transforms/ParallelLoopTiling.cpp
+++ b/mlir/lib/Dialect/SCF/Transforms/ParallelLoopTiling.cpp
@@ -62,10 +62,11 @@ mlir::scf::tileParallelLoop(ParallelOp op, ArrayRef<int64_t> tileSizes,
   SmallVector<Value, 2> tileSizeConstants;
   tileSizeConstants.reserve(op.getUpperBound().size());
   for (size_t i = 0, end = op.getUpperBound().size(); i != end; ++i) {
-    if (i < tileSizes.size())
+    if (i < tileSizes.size()) {
+      assert(tileSizes[i]);
       tileSizeConstants.push_back(
           b.create<arith::ConstantIndexOp>(op.getLoc(), tileSizes[i]));
-    else
+    } else
       // Just pick 1 for the remaining dimensions.
       tileSizeConstants.push_back(
           b.create<arith::ConstantIndexOp>(op.getLoc(), 1));
diff --git a/mlir/test/Dialect/SCF/parallel-loop-tiling-tile-size-check.mlir b/mlir/test/Dialect/SCF/parallel-loop-tiling-tile-size-check.mlir
new file mode 100644
index 000000000000000..bcbf79a80de2759
--- /dev/null
+++ b/mlir/test/Dialect/SCF/parallel-loop-tiling-tile-size-check.mlir
@@ -0,0 +1,8 @@
+// RUN: mlir-opt %s -pass-pipeline='builtin.module(func.func(scf-parallel-loop-tiling{parallel-loop-tile-sizes=0}))' -split-input-file
+
+// XFAIL: *
+
+func.func @parallel_loop(%arg0 : index, %arg1 : index, %arg2 : index) {
+  scf.parallel (%i0) = (%arg0) to (%arg1) step (%arg2) {}
+  return
+}

>From c10d12f7093bd046bdc659364a06598fd53987ad Mon Sep 17 00:00:00 2001
From: justinfargnoli <justinfargnoli at gmail.com>
Date: Sun, 8 Oct 2023 20:42:51 -0700
Subject: [PATCH 06/16] Revert "White space changes"

This reverts commit 91e3bce5e91351494771535613e67ff9f9152405.
---
 mlir/examples/jus/CMakeLists.txt | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/mlir/examples/jus/CMakeLists.txt b/mlir/examples/jus/CMakeLists.txt
index bc705c5d900df67..eaba0544cc073c3 100644
--- a/mlir/examples/jus/CMakeLists.txt
+++ b/mlir/examples/jus/CMakeLists.txt
@@ -1,6 +1,7 @@
 add_custom_target(Jus)
 set_target_properties(Jus PROPERTIES FOLDER Examples)
 
+
 add_dependencies(Jus jusc)
 add_llvm_example(jusc
   toyc.cpp 
@@ -11,6 +12,7 @@ set(LLVM_LINK_COMPONENTS
   Support
   )
 
+
 include_directories(include/)
 target_link_libraries(jusc
   PRIVATE

>From 9f478a67a7d8850955a42d6995e701e594603508 Mon Sep 17 00:00:00 2001
From: justinfargnoli <justinfargnoli at gmail.com>
Date: Sun, 8 Oct 2023 20:43:15 -0700
Subject: [PATCH 07/16] Revert "Fresh copy of Toy Ch1"

This reverts commit 71708753642d2ee6f8fdedf2423d573a3165eb67.
---
 mlir/examples/CMakeLists.txt                  |  2 +-
 mlir/examples/jus/CMakeLists.txt              | 19 ----------
 mlir/examples/lisp/CMakeLists.txt             | 16 ++++++++
 .../{jus/include/toy => lisp/lisp}/AST.h      | 16 ++++----
 .../{jus/include/toy => lisp/lisp}/Lexer.h    | 38 +++++--------------
 .../{jus/include/toy => lisp/lisp}/Parser.h   |  6 +--
 .../examples/{jus/toyc.cpp => lisp/lispc.cpp} | 16 ++++----
 mlir/examples/{jus => lisp}/parser/AST.cpp    | 12 +++---
 8 files changed, 51 insertions(+), 74 deletions(-)
 delete mode 100644 mlir/examples/jus/CMakeLists.txt
 create mode 100644 mlir/examples/lisp/CMakeLists.txt
 rename mlir/examples/{jus/include/toy => lisp/lisp}/AST.h (96%)
 rename mlir/examples/{jus/include/toy => lisp/lisp}/Lexer.h (90%)
 rename mlir/examples/{jus/include/toy => lisp/lisp}/Parser.h (99%)
 rename mlir/examples/{jus/toyc.cpp => lisp/lispc.cpp} (78%)
 rename mlir/examples/{jus => lisp}/parser/AST.cpp (96%)

diff --git a/mlir/examples/CMakeLists.txt b/mlir/examples/CMakeLists.txt
index e90ec13db1acf04..734d5c83abef6cd 100644
--- a/mlir/examples/CMakeLists.txt
+++ b/mlir/examples/CMakeLists.txt
@@ -1,4 +1,4 @@
 add_subdirectory(toy)
 add_subdirectory(transform)
 add_subdirectory(minimal-opt)
-add_subdirectory(jus)
+add_subdirectory(lisp)
diff --git a/mlir/examples/jus/CMakeLists.txt b/mlir/examples/jus/CMakeLists.txt
deleted file mode 100644
index eaba0544cc073c3..000000000000000
--- a/mlir/examples/jus/CMakeLists.txt
+++ /dev/null
@@ -1,19 +0,0 @@
-add_custom_target(Jus)
-set_target_properties(Jus PROPERTIES FOLDER Examples)
-
-
-add_dependencies(Jus jusc)
-add_llvm_example(jusc
-  toyc.cpp 
-  parser/AST.cpp
-  )
-
-set(LLVM_LINK_COMPONENTS
-  Support
-  )
-
-
-include_directories(include/)
-target_link_libraries(jusc
-  PRIVATE
-    MLIRSupport)
diff --git a/mlir/examples/lisp/CMakeLists.txt b/mlir/examples/lisp/CMakeLists.txt
new file mode 100644
index 000000000000000..35bfe7804cbb270
--- /dev/null
+++ b/mlir/examples/lisp/CMakeLists.txt
@@ -0,0 +1,16 @@
+add_custom_target(Lisp)
+set_target_properties(Lisp PROPERTIES FOLDER Examples)
+
+
+add_dependencies(Lisp lispc)
+add_llvm_example(lispc lispc.cpp parser/AST.cpp)
+
+set(LLVM_LINK_COMPONENTS
+  Support
+  )
+
+
+include_directories(include/)
+target_link_libraries(lispc
+  PRIVATE
+    MLIRSupport)
diff --git a/mlir/examples/jus/include/toy/AST.h b/mlir/examples/lisp/lisp/AST.h
similarity index 96%
rename from mlir/examples/jus/include/toy/AST.h
rename to mlir/examples/lisp/lisp/AST.h
index d2ba101dea5a412..8571b5d9f88c1b2 100644
--- a/mlir/examples/jus/include/toy/AST.h
+++ b/mlir/examples/lisp/lisp/AST.h
@@ -1,4 +1,4 @@
-//===- AST.h - Node definition for the Toy AST ----------------------------===//
+//===- AST.h - Node definition for the Lisp AST ----------------------------===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
@@ -6,16 +6,16 @@
 //
 //===----------------------------------------------------------------------===//
 //
-// This file implements the AST for the Toy language. It is optimized for
+// This file implements the AST for the Lisp language. It is optimized for
 // simplicity, not efficiency. The AST forms a tree structure where each node
 // references its children using std::unique_ptr<>.
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef TOY_AST_H
-#define TOY_AST_H
+#ifndef LISP_AST_H
+#define LISP_AST_H
 
-#include "toy/Lexer.h"
+#include "lisp/Lexer.h"
 
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/StringRef.h"
@@ -24,7 +24,7 @@
 #include <vector>
 #include <optional>
 
-namespace toy {
+namespace lisp {
 
 /// A variable type with shape information.
 struct VarType {
@@ -241,6 +241,6 @@ class ModuleAST {
 
 void dump(ModuleAST &);
 
-} // namespace toy
+} // namespace lisp
 
-#endif // TOY_AST_H
+#endif // LISP_AST_H
diff --git a/mlir/examples/jus/include/toy/Lexer.h b/mlir/examples/lisp/lisp/Lexer.h
similarity index 90%
rename from mlir/examples/jus/include/toy/Lexer.h
rename to mlir/examples/lisp/lisp/Lexer.h
index ecbb3b4e0e5835a..5b06bbc76ce3c94 100644
--- a/mlir/examples/jus/include/toy/Lexer.h
+++ b/mlir/examples/lisp/lisp/Lexer.h
@@ -1,4 +1,4 @@
-//===- Lexer.h - Lexer for the Toy language -------------------------------===//
+//===- Lexer.h - Lexer for the Lisp language -------------------------------===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
@@ -6,19 +6,19 @@
 //
 //===----------------------------------------------------------------------===//
 //
-// This file implements a simple Lexer for the Toy language.
+// This file implements a simple Lexer for the Lisp language.
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef TOY_LEXER_H
-#define TOY_LEXER_H
+#ifndef LISP_LEXER_H
+#define LISP_LEXER_H
 
 #include "llvm/ADT/StringRef.h"
 
 #include <memory>
 #include <string>
 
-namespace toy {
+namespace lisp {
 
 /// Structure definition a location in a file.
 struct Location {
@@ -29,24 +29,11 @@ struct Location {
 
 // List of Token returned by the lexer.
 enum Token : int {
-  tok_semicolon = ';',
   tok_parenthese_open = '(',
   tok_parenthese_close = ')',
-  tok_bracket_open = '{',
-  tok_bracket_close = '}',
-  tok_sbracket_open = '[',
-  tok_sbracket_close = ']',
-
   tok_eof = -1,
-
-  // commands
-  tok_return = -2,
-  tok_var = -3,
-  tok_def = -4,
-
-  // primary
-  tok_identifier = -5,
-  tok_number = -6,
+  tok_number = -2,
+  tok_identifier = -3
 };
 
 /// The Lexer is an abstract base class providing all the facilities that the
@@ -138,13 +125,6 @@ class Lexer {
       identifierStr = (char)lastChar;
       while (isalnum((lastChar = Token(getNextChar()))) || lastChar == '_')
         identifierStr += (char)lastChar;
-
-      if (identifierStr == "return")
-        return tok_return;
-      if (identifierStr == "def")
-        return tok_def;
-      if (identifierStr == "var")
-        return tok_var;
       return tok_identifier;
     }
 
@@ -227,6 +207,6 @@ class LexerBuffer final : public Lexer {
   }
   const char *current, *end;
 };
-} // namespace toy
+} // namespace lisp
 
-#endif // TOY_LEXER_H
+#endif // LISP_LEXER_H
diff --git a/mlir/examples/jus/include/toy/Parser.h b/mlir/examples/lisp/lisp/Parser.h
similarity index 99%
rename from mlir/examples/jus/include/toy/Parser.h
rename to mlir/examples/lisp/lisp/Parser.h
index 1f20616ac6b4e14..5cd884e686aa992 100644
--- a/mlir/examples/jus/include/toy/Parser.h
+++ b/mlir/examples/lisp/lisp/Parser.h
@@ -14,8 +14,8 @@
 #ifndef TOY_PARSER_H
 #define TOY_PARSER_H
 
-#include "toy/AST.h"
-#include "toy/Lexer.h"
+#include "lisp/AST.h"
+#include "lisp/Lexer.h"
 
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/StringExtras.h"
@@ -26,7 +26,7 @@
 #include <vector>
 #include <optional>
 
-namespace toy {
+namespace lisp {
 
 /// This is a simple recursive parser for the Toy language. It produces a well
 /// formed AST from a stream of Token supplied by the Lexer. No semantic checks
diff --git a/mlir/examples/jus/toyc.cpp b/mlir/examples/lisp/lispc.cpp
similarity index 78%
rename from mlir/examples/jus/toyc.cpp
rename to mlir/examples/lisp/lispc.cpp
index ca2a1a1fa8adfc4..9f9920224a5296d 100644
--- a/mlir/examples/jus/toyc.cpp
+++ b/mlir/examples/lisp/lispc.cpp
@@ -1,4 +1,4 @@
-//===- toyc.cpp - The Toy Compiler ----------------------------------------===//
+//===- lispc.cpp - The Lisp Compiler ----------------------------------------===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
@@ -6,11 +6,11 @@
 //
 //===----------------------------------------------------------------------===//
 //
-// This file implements the entry point for the Toy compiler.
+// This file implements the entry point for the Lisp compiler.
 //
 //===----------------------------------------------------------------------===//
 
-#include "toy/Parser.h"
+#include "lisp/Parser.h"
 
 #include "llvm/ADT/StringRef.h"
 #include "llvm/Support/CommandLine.h"
@@ -18,11 +18,11 @@
 #include "llvm/Support/MemoryBuffer.h"
 #include "llvm/Support/raw_ostream.h"
 
-using namespace toy;
+using namespace lisp;
 namespace cl = llvm::cl;
 
 static cl::opt<std::string> inputFilename(cl::Positional,
-                                          cl::desc("<input toy file>"),
+                                          cl::desc("<input lisp file>"),
                                           cl::init("-"),
                                           cl::value_desc("filename"));
 namespace {
@@ -33,8 +33,8 @@ static cl::opt<enum Action>
     emitAction("emit", cl::desc("Select the kind of output desired"),
                cl::values(clEnumValN(DumpAST, "ast", "output the AST dump")));
 
-/// Returns a Toy AST resulting from parsing the file or a nullptr on error.
-std::unique_ptr<toy::ModuleAST> parseInputFile(llvm::StringRef filename) {
+/// Returns a Lisp AST resulting from parsing the file or a nullptr on error.
+std::unique_ptr<lisp::ModuleAST> parseInputFile(llvm::StringRef filename) {
   llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> fileOrErr =
       llvm::MemoryBuffer::getFileOrSTDIN(filename);
   if (std::error_code ec = fileOrErr.getError()) {
@@ -48,7 +48,7 @@ std::unique_ptr<toy::ModuleAST> parseInputFile(llvm::StringRef filename) {
 }
 
 int main(int argc, char **argv) {
-  cl::ParseCommandLineOptions(argc, argv, "toy compiler\n");
+  cl::ParseCommandLineOptions(argc, argv, "lisp compiler\n");
 
   auto moduleAST = parseInputFile(inputFilename);
   if (!moduleAST)
diff --git a/mlir/examples/jus/parser/AST.cpp b/mlir/examples/lisp/parser/AST.cpp
similarity index 96%
rename from mlir/examples/jus/parser/AST.cpp
rename to mlir/examples/lisp/parser/AST.cpp
index 2eaabb1b529e1b8..99bde6b8df5e525 100644
--- a/mlir/examples/jus/parser/AST.cpp
+++ b/mlir/examples/lisp/parser/AST.cpp
@@ -1,4 +1,4 @@
-//===- AST.cpp - Helper for printing out the Toy AST ----------------------===//
+//===- AST.cpp - Helper for printing out the Lisp AST ----------------------===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
@@ -6,17 +6,17 @@
 //
 //===----------------------------------------------------------------------===//
 //
-// This file implements the AST dump for the Toy language.
+// This file implements the AST dump for the Lisp language.
 //
 //===----------------------------------------------------------------------===//
 
-#include "toy/AST.h"
+#include "lisp/AST.h"
 
 #include "llvm/ADT/Twine.h"
 #include "llvm/ADT/TypeSwitch.h"
 #include "llvm/Support/raw_ostream.h"
 
-using namespace toy;
+using namespace lisp;
 
 namespace {
 
@@ -226,9 +226,9 @@ void ASTDumper::dump(ModuleAST *node) {
     dump(&f);
 }
 
-namespace toy {
+namespace lisp {
 
 // Public API
 void dump(ModuleAST &module) { ASTDumper().dump(&module); }
 
-} // namespace toy
+} // namespace lisp

>From 845bdf0d5f165a274208dc5cecb970ae9789b9d1 Mon Sep 17 00:00:00 2001
From: justinfargnoli <justinfargnoli at gmail.com>
Date: Sun, 8 Oct 2023 20:43:30 -0700
Subject: [PATCH 08/16] Revert "Saving initial copy of Toy Ch1 as Lisp"

This reverts commit 8ec540ab75a4ed04dfed0021c4279cad217ff262.
---
 mlir/examples/lisp/CMakeLists.txt |  16 -
 mlir/examples/lisp/lisp/AST.h     | 246 ---------------
 mlir/examples/lisp/lisp/Lexer.h   | 212 -------------
 mlir/examples/lisp/lisp/Parser.h  | 489 ------------------------------
 mlir/examples/lisp/lispc.cpp      |  66 ----
 mlir/examples/lisp/parser/AST.cpp | 234 --------------
 6 files changed, 1263 deletions(-)
 delete mode 100644 mlir/examples/lisp/CMakeLists.txt
 delete mode 100644 mlir/examples/lisp/lisp/AST.h
 delete mode 100644 mlir/examples/lisp/lisp/Lexer.h
 delete mode 100644 mlir/examples/lisp/lisp/Parser.h
 delete mode 100644 mlir/examples/lisp/lispc.cpp
 delete mode 100644 mlir/examples/lisp/parser/AST.cpp

diff --git a/mlir/examples/lisp/CMakeLists.txt b/mlir/examples/lisp/CMakeLists.txt
deleted file mode 100644
index 35bfe7804cbb270..000000000000000
--- a/mlir/examples/lisp/CMakeLists.txt
+++ /dev/null
@@ -1,16 +0,0 @@
-add_custom_target(Lisp)
-set_target_properties(Lisp PROPERTIES FOLDER Examples)
-
-
-add_dependencies(Lisp lispc)
-add_llvm_example(lispc lispc.cpp parser/AST.cpp)
-
-set(LLVM_LINK_COMPONENTS
-  Support
-  )
-
-
-include_directories(include/)
-target_link_libraries(lispc
-  PRIVATE
-    MLIRSupport)
diff --git a/mlir/examples/lisp/lisp/AST.h b/mlir/examples/lisp/lisp/AST.h
deleted file mode 100644
index 8571b5d9f88c1b2..000000000000000
--- a/mlir/examples/lisp/lisp/AST.h
+++ /dev/null
@@ -1,246 +0,0 @@
-//===- AST.h - Node definition for the Lisp AST ----------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// This file implements the AST for the Lisp language. It is optimized for
-// simplicity, not efficiency. The AST forms a tree structure where each node
-// references its children using std::unique_ptr<>.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LISP_AST_H
-#define LISP_AST_H
-
-#include "lisp/Lexer.h"
-
-#include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/Support/Casting.h"
-#include <utility>
-#include <vector>
-#include <optional>
-
-namespace lisp {
-
-/// A variable type with shape information.
-struct VarType {
-  std::vector<int64_t> shape;
-};
-
-/// Base class for all expression nodes.
-class ExprAST {
-public:
-  enum ExprASTKind {
-    Expr_VarDecl,
-    Expr_Return,
-    Expr_Num,
-    Expr_Literal,
-    Expr_Var,
-    Expr_BinOp,
-    Expr_Call,
-    Expr_Print,
-  };
-
-  ExprAST(ExprASTKind kind, Location location)
-      : kind(kind), location(std::move(location)) {}
-  virtual ~ExprAST() = default;
-
-  ExprASTKind getKind() const { return kind; }
-
-  const Location &loc() { return location; }
-
-private:
-  const ExprASTKind kind;
-  Location location;
-};
-
-/// A block-list of expressions.
-using ExprASTList = std::vector<std::unique_ptr<ExprAST>>;
-
-/// Expression class for numeric literals like "1.0".
-class NumberExprAST : public ExprAST {
-  double val;
-
-public:
-  NumberExprAST(Location loc, double val)
-      : ExprAST(Expr_Num, std::move(loc)), val(val) {}
-
-  double getValue() { return val; }
-
-  /// LLVM style RTTI
-  static bool classof(const ExprAST *c) { return c->getKind() == Expr_Num; }
-};
-
-/// Expression class for a literal value.
-class LiteralExprAST : public ExprAST {
-  std::vector<std::unique_ptr<ExprAST>> values;
-  std::vector<int64_t> dims;
-
-public:
-  LiteralExprAST(Location loc, std::vector<std::unique_ptr<ExprAST>> values,
-                 std::vector<int64_t> dims)
-      : ExprAST(Expr_Literal, std::move(loc)), values(std::move(values)),
-        dims(std::move(dims)) {}
-
-  llvm::ArrayRef<std::unique_ptr<ExprAST>> getValues() { return values; }
-  llvm::ArrayRef<int64_t> getDims() { return dims; }
-
-  /// LLVM style RTTI
-  static bool classof(const ExprAST *c) { return c->getKind() == Expr_Literal; }
-};
-
-/// Expression class for referencing a variable, like "a".
-class VariableExprAST : public ExprAST {
-  std::string name;
-
-public:
-  VariableExprAST(Location loc, llvm::StringRef name)
-      : ExprAST(Expr_Var, std::move(loc)), name(name) {}
-
-  llvm::StringRef getName() { return name; }
-
-  /// LLVM style RTTI
-  static bool classof(const ExprAST *c) { return c->getKind() == Expr_Var; }
-};
-
-/// Expression class for defining a variable.
-class VarDeclExprAST : public ExprAST {
-  std::string name;
-  VarType type;
-  std::unique_ptr<ExprAST> initVal;
-
-public:
-  VarDeclExprAST(Location loc, llvm::StringRef name, VarType type,
-                 std::unique_ptr<ExprAST> initVal)
-      : ExprAST(Expr_VarDecl, std::move(loc)), name(name),
-        type(std::move(type)), initVal(std::move(initVal)) {}
-
-  llvm::StringRef getName() { return name; }
-  ExprAST *getInitVal() { return initVal.get(); }
-  const VarType &getType() { return type; }
-
-  /// LLVM style RTTI
-  static bool classof(const ExprAST *c) { return c->getKind() == Expr_VarDecl; }
-};
-
-/// Expression class for a return operator.
-class ReturnExprAST : public ExprAST {
-  std::optional<std::unique_ptr<ExprAST>> expr;
-
-public:
-  ReturnExprAST(Location loc, std::optional<std::unique_ptr<ExprAST>> expr)
-      : ExprAST(Expr_Return, std::move(loc)), expr(std::move(expr)) {}
-
-  std::optional<ExprAST *> getExpr() {
-    if (expr.has_value())
-      return expr->get();
-    return std::nullopt;
-  }
-
-  /// LLVM style RTTI
-  static bool classof(const ExprAST *c) { return c->getKind() == Expr_Return; }
-};
-
-/// Expression class for a binary operator.
-class BinaryExprAST : public ExprAST {
-  char op;
-  std::unique_ptr<ExprAST> lhs, rhs;
-
-public:
-  char getOp() { return op; }
-  ExprAST *getLHS() { return lhs.get(); }
-  ExprAST *getRHS() { return rhs.get(); }
-
-  BinaryExprAST(Location loc, char op, std::unique_ptr<ExprAST> lhs,
-                std::unique_ptr<ExprAST> rhs)
-      : ExprAST(Expr_BinOp, std::move(loc)), op(op), lhs(std::move(lhs)),
-        rhs(std::move(rhs)) {}
-
-  /// LLVM style RTTI
-  static bool classof(const ExprAST *c) { return c->getKind() == Expr_BinOp; }
-};
-
-/// Expression class for function calls.
-class CallExprAST : public ExprAST {
-  std::string callee;
-  std::vector<std::unique_ptr<ExprAST>> args;
-
-public:
-  CallExprAST(Location loc, const std::string &callee,
-              std::vector<std::unique_ptr<ExprAST>> args)
-      : ExprAST(Expr_Call, std::move(loc)), callee(callee),
-        args(std::move(args)) {}
-
-  llvm::StringRef getCallee() { return callee; }
-  llvm::ArrayRef<std::unique_ptr<ExprAST>> getArgs() { return args; }
-
-  /// LLVM style RTTI
-  static bool classof(const ExprAST *c) { return c->getKind() == Expr_Call; }
-};
-
-/// Expression class for builtin print calls.
-class PrintExprAST : public ExprAST {
-  std::unique_ptr<ExprAST> arg;
-
-public:
-  PrintExprAST(Location loc, std::unique_ptr<ExprAST> arg)
-      : ExprAST(Expr_Print, std::move(loc)), arg(std::move(arg)) {}
-
-  ExprAST *getArg() { return arg.get(); }
-
-  /// LLVM style RTTI
-  static bool classof(const ExprAST *c) { return c->getKind() == Expr_Print; }
-};
-
-/// This class represents the "prototype" for a function, which captures its
-/// name, and its argument names (thus implicitly the number of arguments the
-/// function takes).
-class PrototypeAST {
-  Location location;
-  std::string name;
-  std::vector<std::unique_ptr<VariableExprAST>> args;
-
-public:
-  PrototypeAST(Location location, const std::string &name,
-               std::vector<std::unique_ptr<VariableExprAST>> args)
-      : location(std::move(location)), name(name), args(std::move(args)) {}
-
-  const Location &loc() { return location; }
-  llvm::StringRef getName() const { return name; }
-  llvm::ArrayRef<std::unique_ptr<VariableExprAST>> getArgs() { return args; }
-};
-
-/// This class represents a function definition itself.
-class FunctionAST {
-  std::unique_ptr<PrototypeAST> proto;
-  std::unique_ptr<ExprASTList> body;
-
-public:
-  FunctionAST(std::unique_ptr<PrototypeAST> proto,
-              std::unique_ptr<ExprASTList> body)
-      : proto(std::move(proto)), body(std::move(body)) {}
-  PrototypeAST *getProto() { return proto.get(); }
-  ExprASTList *getBody() { return body.get(); }
-};
-
-/// This class represents a list of functions to be processed together
-class ModuleAST {
-  std::vector<FunctionAST> functions;
-
-public:
-  ModuleAST(std::vector<FunctionAST> functions)
-      : functions(std::move(functions)) {}
-
-  auto begin() { return functions.begin(); }
-  auto end() { return functions.end(); }
-};
-
-void dump(ModuleAST &);
-
-} // namespace lisp
-
-#endif // LISP_AST_H
diff --git a/mlir/examples/lisp/lisp/Lexer.h b/mlir/examples/lisp/lisp/Lexer.h
deleted file mode 100644
index 5b06bbc76ce3c94..000000000000000
--- a/mlir/examples/lisp/lisp/Lexer.h
+++ /dev/null
@@ -1,212 +0,0 @@
-//===- Lexer.h - Lexer for the Lisp language -------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// This file implements a simple Lexer for the Lisp language.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LISP_LEXER_H
-#define LISP_LEXER_H
-
-#include "llvm/ADT/StringRef.h"
-
-#include <memory>
-#include <string>
-
-namespace lisp {
-
-/// Structure definition a location in a file.
-struct Location {
-  std::shared_ptr<std::string> file; ///< filename.
-  int line;                          ///< line number.
-  int col;                           ///< column number.
-};
-
-// List of Token returned by the lexer.
-enum Token : int {
-  tok_parenthese_open = '(',
-  tok_parenthese_close = ')',
-  tok_eof = -1,
-  tok_number = -2,
-  tok_identifier = -3
-};
-
-/// The Lexer is an abstract base class providing all the facilities that the
-/// Parser expects. It goes through the stream one token at a time and keeps
-/// track of the location in the file for debugging purposes.
-/// It relies on a subclass to provide a `readNextLine()` method. The subclass
-/// can proceed by reading the next line from the standard input or from a
-/// memory mapped file.
-class Lexer {
-public:
-  /// Create a lexer for the given filename. The filename is kept only for
-  /// debugging purposes (attaching a location to a Token).
-  Lexer(std::string filename)
-      : lastLocation(
-            {std::make_shared<std::string>(std::move(filename)), 0, 0}) {}
-  virtual ~Lexer() = default;
-
-  /// Look at the current token in the stream.
-  Token getCurToken() { return curTok; }
-
-  /// Move to the next token in the stream and return it.
-  Token getNextToken() { return curTok = getTok(); }
-
-  /// Move to the next token in the stream, asserting on the current token
-  /// matching the expectation.
-  void consume(Token tok) {
-    assert(tok == curTok && "consume Token mismatch expectation");
-    getNextToken();
-  }
-
-  /// Return the current identifier (prereq: getCurToken() == tok_identifier)
-  llvm::StringRef getId() {
-    assert(curTok == tok_identifier);
-    return identifierStr;
-  }
-
-  /// Return the current number (prereq: getCurToken() == tok_number)
-  double getValue() {
-    assert(curTok == tok_number);
-    return numVal;
-  }
-
-  /// Return the location for the beginning of the current token.
-  Location getLastLocation() { return lastLocation; }
-
-  // Return the current line in the file.
-  int getLine() { return curLineNum; }
-
-  // Return the current column in the file.
-  int getCol() { return curCol; }
-
-private:
-  /// Delegate to a derived class fetching the next line. Returns an empty
-  /// string to signal end of file (EOF). Lines are expected to always finish
-  /// with "\n"
-  virtual llvm::StringRef readNextLine() = 0;
-
-  /// Return the next character from the stream. This manages the buffer for the
-  /// current line and request the next line buffer to the derived class as
-  /// needed.
-  int getNextChar() {
-    // The current line buffer should not be empty unless it is the end of file.
-    if (curLineBuffer.empty())
-      return EOF;
-    ++curCol;
-    auto nextchar = curLineBuffer.front();
-    curLineBuffer = curLineBuffer.drop_front();
-    if (curLineBuffer.empty())
-      curLineBuffer = readNextLine();
-    if (nextchar == '\n') {
-      ++curLineNum;
-      curCol = 0;
-    }
-    return nextchar;
-  }
-
-  ///  Return the next token from standard input.
-  Token getTok() {
-    // Skip any whitespace.
-    while (isspace(lastChar))
-      lastChar = Token(getNextChar());
-
-    // Save the current location before reading the token characters.
-    lastLocation.line = curLineNum;
-    lastLocation.col = curCol;
-
-    // Identifier: [a-zA-Z][a-zA-Z0-9_]*
-    if (isalpha(lastChar)) {
-      identifierStr = (char)lastChar;
-      while (isalnum((lastChar = Token(getNextChar()))) || lastChar == '_')
-        identifierStr += (char)lastChar;
-      return tok_identifier;
-    }
-
-    // Number: [0-9.]+
-    if (isdigit(lastChar) || lastChar == '.') {
-      std::string numStr;
-      do {
-        numStr += lastChar;
-        lastChar = Token(getNextChar());
-      } while (isdigit(lastChar) || lastChar == '.');
-
-      numVal = strtod(numStr.c_str(), nullptr);
-      return tok_number;
-    }
-
-    if (lastChar == '#') {
-      // Comment until end of line.
-      do {
-        lastChar = Token(getNextChar());
-      } while (lastChar != EOF && lastChar != '\n' && lastChar != '\r');
-
-      if (lastChar != EOF)
-        return getTok();
-    }
-
-    // Check for end of file.  Don't eat the EOF.
-    if (lastChar == EOF)
-      return tok_eof;
-
-    // Otherwise, just return the character as its ascii value.
-    Token thisChar = Token(lastChar);
-    lastChar = Token(getNextChar());
-    return thisChar;
-  }
-
-  /// The last token read from the input.
-  Token curTok = tok_eof;
-
-  /// Location for `curTok`.
-  Location lastLocation;
-
-  /// If the current Token is an identifier, this string contains the value.
-  std::string identifierStr;
-
-  /// If the current Token is a number, this contains the value.
-  double numVal = 0;
-
-  /// The last value returned by getNextChar(). We need to keep it around as we
-  /// always need to read ahead one character to decide when to end a token and
-  /// we can't put it back in the stream after reading from it.
-  Token lastChar = Token(' ');
-
-  /// Keep track of the current line number in the input stream
-  int curLineNum = 0;
-
-  /// Keep track of the current column number in the input stream
-  int curCol = 0;
-
-  /// Buffer supplied by the derived class on calls to `readNextLine()`
-  llvm::StringRef curLineBuffer = "\n";
-};
-
-/// A lexer implementation operating on a buffer in memory.
-class LexerBuffer final : public Lexer {
-public:
-  LexerBuffer(const char *begin, const char *end, std::string filename)
-      : Lexer(std::move(filename)), current(begin), end(end) {}
-
-private:
-  /// Provide one line at a time to the Lexer, return an empty string when
-  /// reaching the end of the buffer.
-  llvm::StringRef readNextLine() override {
-    auto *begin = current;
-    while (current <= end && *current && *current != '\n')
-      ++current;
-    if (current <= end && *current)
-      ++current;
-    llvm::StringRef result{begin, static_cast<size_t>(current - begin)};
-    return result;
-  }
-  const char *current, *end;
-};
-} // namespace lisp
-
-#endif // LISP_LEXER_H
diff --git a/mlir/examples/lisp/lisp/Parser.h b/mlir/examples/lisp/lisp/Parser.h
deleted file mode 100644
index 5cd884e686aa992..000000000000000
--- a/mlir/examples/lisp/lisp/Parser.h
+++ /dev/null
@@ -1,489 +0,0 @@
-//===- Parser.h - Toy Language Parser -------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// This file implements the parser for the Toy language. It processes the Token
-// provided by the Lexer and returns an AST.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef TOY_PARSER_H
-#define TOY_PARSER_H
-
-#include "lisp/AST.h"
-#include "lisp/Lexer.h"
-
-#include "llvm/ADT/STLExtras.h"
-#include "llvm/ADT/StringExtras.h"
-#include "llvm/Support/raw_ostream.h"
-
-#include <map>
-#include <utility>
-#include <vector>
-#include <optional>
-
-namespace lisp {
-
-/// This is a simple recursive parser for the Toy language. It produces a well
-/// formed AST from a stream of Token supplied by the Lexer. No semantic checks
-/// or symbol resolution is performed. For example, variables are referenced by
-/// string and the code could reference an undeclared variable and the parsing
-/// succeeds.
-class Parser {
-public:
-  /// Create a Parser for the supplied lexer.
-  Parser(Lexer &lexer) : lexer(lexer) {}
-
-  /// Parse a full Module. A module is a list of function definitions.
-  std::unique_ptr<ModuleAST> parseModule() {
-    lexer.getNextToken(); // prime the lexer
-
-    // Parse functions one at a time and accumulate in this vector.
-    std::vector<FunctionAST> functions;
-    while (auto f = parseDefinition()) {
-      functions.push_back(std::move(*f));
-      if (lexer.getCurToken() == tok_eof)
-        break;
-    }
-    // If we didn't reach EOF, there was an error during parsing
-    if (lexer.getCurToken() != tok_eof)
-      return parseError<ModuleAST>("nothing", "at end of module");
-
-    return std::make_unique<ModuleAST>(std::move(functions));
-  }
-
-private:
-  Lexer &lexer;
-
-  /// Parse a return statement.
-  /// return :== return ; | return expr ;
-  std::unique_ptr<ReturnExprAST> parseReturn() {
-    auto loc = lexer.getLastLocation();
-    lexer.consume(tok_return);
-
-    // return takes an optional argument
-    std::optional<std::unique_ptr<ExprAST>> expr;
-    if (lexer.getCurToken() != ';') {
-      expr = parseExpression();
-      if (!expr)
-        return nullptr;
-    }
-    return std::make_unique<ReturnExprAST>(std::move(loc), std::move(expr));
-  }
-
-  /// Parse a literal number.
-  /// numberexpr ::= number
-  std::unique_ptr<ExprAST> parseNumberExpr() {
-    auto loc = lexer.getLastLocation();
-    auto result =
-        std::make_unique<NumberExprAST>(std::move(loc), lexer.getValue());
-    lexer.consume(tok_number);
-    return std::move(result);
-  }
-
-  /// Parse a literal array expression.
-  /// tensorLiteral ::= [ literalList ] | number
-  /// literalList ::= tensorLiteral | tensorLiteral, literalList
-  std::unique_ptr<ExprAST> parseTensorLiteralExpr() {
-    auto loc = lexer.getLastLocation();
-    lexer.consume(Token('['));
-
-    // Hold the list of values at this nesting level.
-    std::vector<std::unique_ptr<ExprAST>> values;
-    // Hold the dimensions for all the nesting inside this level.
-    std::vector<int64_t> dims;
-    do {
-      // We can have either another nested array or a number literal.
-      if (lexer.getCurToken() == '[') {
-        values.push_back(parseTensorLiteralExpr());
-        if (!values.back())
-          return nullptr; // parse error in the nested array.
-      } else {
-        if (lexer.getCurToken() != tok_number)
-          return parseError<ExprAST>("<num> or [", "in literal expression");
-        values.push_back(parseNumberExpr());
-      }
-
-      // End of this list on ']'
-      if (lexer.getCurToken() == ']')
-        break;
-
-      // Elements are separated by a comma.
-      if (lexer.getCurToken() != ',')
-        return parseError<ExprAST>("] or ,", "in literal expression");
-
-      lexer.getNextToken(); // eat ,
-    } while (true);
-    if (values.empty())
-      return parseError<ExprAST>("<something>", "to fill literal expression");
-    lexer.getNextToken(); // eat ]
-
-    /// Fill in the dimensions now. First the current nesting level:
-    dims.push_back(values.size());
-
-    /// If there is any nested array, process all of them and ensure that
-    /// dimensions are uniform.
-    if (llvm::any_of(values, [](std::unique_ptr<ExprAST> &expr) {
-          return llvm::isa<LiteralExprAST>(expr.get());
-        })) {
-      auto *firstLiteral = llvm::dyn_cast<LiteralExprAST>(values.front().get());
-      if (!firstLiteral)
-        return parseError<ExprAST>("uniform well-nested dimensions",
-                                   "inside literal expression");
-
-      // Append the nested dimensions to the current level
-      auto firstDims = firstLiteral->getDims();
-      dims.insert(dims.end(), firstDims.begin(), firstDims.end());
-
-      // Sanity check that shape is uniform across all elements of the list.
-      for (auto &expr : values) {
-        auto *exprLiteral = llvm::cast<LiteralExprAST>(expr.get());
-        if (!exprLiteral)
-          return parseError<ExprAST>("uniform well-nested dimensions",
-                                     "inside literal expression");
-        if (exprLiteral->getDims() != firstDims)
-          return parseError<ExprAST>("uniform well-nested dimensions",
-                                     "inside literal expression");
-      }
-    }
-    return std::make_unique<LiteralExprAST>(std::move(loc), std::move(values),
-                                            std::move(dims));
-  }
-
-  /// parenexpr ::= '(' expression ')'
-  std::unique_ptr<ExprAST> parseParenExpr() {
-    lexer.getNextToken(); // eat (.
-    auto v = parseExpression();
-    if (!v)
-      return nullptr;
-
-    if (lexer.getCurToken() != ')')
-      return parseError<ExprAST>(")", "to close expression with parentheses");
-    lexer.consume(Token(')'));
-    return v;
-  }
-
-  /// identifierexpr
-  ///   ::= identifier
-  ///   ::= identifier '(' expression ')'
-  std::unique_ptr<ExprAST> parseIdentifierExpr() {
-    std::string name(lexer.getId());
-
-    auto loc = lexer.getLastLocation();
-    lexer.getNextToken(); // eat identifier.
-
-    if (lexer.getCurToken() != '(') // Simple variable ref.
-      return std::make_unique<VariableExprAST>(std::move(loc), name);
-
-    // This is a function call.
-    lexer.consume(Token('('));
-    std::vector<std::unique_ptr<ExprAST>> args;
-    if (lexer.getCurToken() != ')') {
-      while (true) {
-        if (auto arg = parseExpression())
-          args.push_back(std::move(arg));
-        else
-          return nullptr;
-
-        if (lexer.getCurToken() == ')')
-          break;
-
-        if (lexer.getCurToken() != ',')
-          return parseError<ExprAST>(", or )", "in argument list");
-        lexer.getNextToken();
-      }
-    }
-    lexer.consume(Token(')'));
-
-    // It can be a builtin call to print
-    if (name == "print") {
-      if (args.size() != 1)
-        return parseError<ExprAST>("<single arg>", "as argument to print()");
-
-      return std::make_unique<PrintExprAST>(std::move(loc), std::move(args[0]));
-    }
-
-    // Call to a user-defined function
-    return std::make_unique<CallExprAST>(std::move(loc), name, std::move(args));
-  }
-
-  /// primary
-  ///   ::= identifierexpr
-  ///   ::= numberexpr
-  ///   ::= parenexpr
-  ///   ::= tensorliteral
-  std::unique_ptr<ExprAST> parsePrimary() {
-    switch (lexer.getCurToken()) {
-    default:
-      llvm::errs() << "unknown token '" << lexer.getCurToken()
-                   << "' when expecting an expression\n";
-      return nullptr;
-    case tok_identifier:
-      return parseIdentifierExpr();
-    case tok_number:
-      return parseNumberExpr();
-    case '(':
-      return parseParenExpr();
-    case '[':
-      return parseTensorLiteralExpr();
-    case ';':
-      return nullptr;
-    case '}':
-      return nullptr;
-    }
-  }
-
-  /// Recursively parse the right hand side of a binary expression, the ExprPrec
-  /// argument indicates the precedence of the current binary operator.
-  ///
-  /// binoprhs ::= ('+' primary)*
-  std::unique_ptr<ExprAST> parseBinOpRHS(int exprPrec,
-                                         std::unique_ptr<ExprAST> lhs) {
-    // If this is a binop, find its precedence.
-    while (true) {
-      int tokPrec = getTokPrecedence();
-
-      // If this is a binop that binds at least as tightly as the current binop,
-      // consume it, otherwise we are done.
-      if (tokPrec < exprPrec)
-        return lhs;
-
-      // Okay, we know this is a binop.
-      int binOp = lexer.getCurToken();
-      lexer.consume(Token(binOp));
-      auto loc = lexer.getLastLocation();
-
-      // Parse the primary expression after the binary operator.
-      auto rhs = parsePrimary();
-      if (!rhs)
-        return parseError<ExprAST>("expression", "to complete binary operator");
-
-      // If BinOp binds less tightly with rhs than the operator after rhs, let
-      // the pending operator take rhs as its lhs.
-      int nextPrec = getTokPrecedence();
-      if (tokPrec < nextPrec) {
-        rhs = parseBinOpRHS(tokPrec + 1, std::move(rhs));
-        if (!rhs)
-          return nullptr;
-      }
-
-      // Merge lhs/RHS.
-      lhs = std::make_unique<BinaryExprAST>(std::move(loc), binOp,
-                                            std::move(lhs), std::move(rhs));
-    }
-  }
-
-  /// expression::= primary binop rhs
-  std::unique_ptr<ExprAST> parseExpression() {
-    auto lhs = parsePrimary();
-    if (!lhs)
-      return nullptr;
-
-    return parseBinOpRHS(0, std::move(lhs));
-  }
-
-  /// type ::= < shape_list >
-  /// shape_list ::= num | num , shape_list
-  std::unique_ptr<VarType> parseType() {
-    if (lexer.getCurToken() != '<')
-      return parseError<VarType>("<", "to begin type");
-    lexer.getNextToken(); // eat <
-
-    auto type = std::make_unique<VarType>();
-
-    while (lexer.getCurToken() == tok_number) {
-      type->shape.push_back(lexer.getValue());
-      lexer.getNextToken();
-      if (lexer.getCurToken() == ',')
-        lexer.getNextToken();
-    }
-
-    if (lexer.getCurToken() != '>')
-      return parseError<VarType>(">", "to end type");
-    lexer.getNextToken(); // eat >
-    return type;
-  }
-
-  /// Parse a variable declaration, it starts with a `var` keyword followed by
-  /// and identifier and an optional type (shape specification) before the
-  /// initializer.
-  /// decl ::= var identifier [ type ] = expr
-  std::unique_ptr<VarDeclExprAST> parseDeclaration() {
-    if (lexer.getCurToken() != tok_var)
-      return parseError<VarDeclExprAST>("var", "to begin declaration");
-    auto loc = lexer.getLastLocation();
-    lexer.getNextToken(); // eat var
-
-    if (lexer.getCurToken() != tok_identifier)
-      return parseError<VarDeclExprAST>("identified",
-                                        "after 'var' declaration");
-    std::string id(lexer.getId());
-    lexer.getNextToken(); // eat id
-
-    std::unique_ptr<VarType> type; // Type is optional, it can be inferred
-    if (lexer.getCurToken() == '<') {
-      type = parseType();
-      if (!type)
-        return nullptr;
-    }
-
-    if (!type)
-      type = std::make_unique<VarType>();
-    lexer.consume(Token('='));
-    auto expr = parseExpression();
-    return std::make_unique<VarDeclExprAST>(std::move(loc), std::move(id),
-                                            std::move(*type), std::move(expr));
-  }
-
-  /// Parse a block: a list of expression separated by semicolons and wrapped in
-  /// curly braces.
-  ///
-  /// block ::= { expression_list }
-  /// expression_list ::= block_expr ; expression_list
-  /// block_expr ::= decl | "return" | expr
-  std::unique_ptr<ExprASTList> parseBlock() {
-    if (lexer.getCurToken() != '{')
-      return parseError<ExprASTList>("{", "to begin block");
-    lexer.consume(Token('{'));
-
-    auto exprList = std::make_unique<ExprASTList>();
-
-    // Ignore empty expressions: swallow sequences of semicolons.
-    while (lexer.getCurToken() == ';')
-      lexer.consume(Token(';'));
-
-    while (lexer.getCurToken() != '}' && lexer.getCurToken() != tok_eof) {
-      if (lexer.getCurToken() == tok_var) {
-        // Variable declaration
-        auto varDecl = parseDeclaration();
-        if (!varDecl)
-          return nullptr;
-        exprList->push_back(std::move(varDecl));
-      } else if (lexer.getCurToken() == tok_return) {
-        // Return statement
-        auto ret = parseReturn();
-        if (!ret)
-          return nullptr;
-        exprList->push_back(std::move(ret));
-      } else {
-        // General expression
-        auto expr = parseExpression();
-        if (!expr)
-          return nullptr;
-        exprList->push_back(std::move(expr));
-      }
-      // Ensure that elements are separated by a semicolon.
-      if (lexer.getCurToken() != ';')
-        return parseError<ExprASTList>(";", "after expression");
-
-      // Ignore empty expressions: swallow sequences of semicolons.
-      while (lexer.getCurToken() == ';')
-        lexer.consume(Token(';'));
-    }
-
-    if (lexer.getCurToken() != '}')
-      return parseError<ExprASTList>("}", "to close block");
-
-    lexer.consume(Token('}'));
-    return exprList;
-  }
-
-  /// prototype ::= def id '(' decl_list ')'
-  /// decl_list ::= identifier | identifier, decl_list
-  std::unique_ptr<PrototypeAST> parsePrototype() {
-    auto loc = lexer.getLastLocation();
-
-    if (lexer.getCurToken() != tok_def)
-      return parseError<PrototypeAST>("def", "in prototype");
-    lexer.consume(tok_def);
-
-    if (lexer.getCurToken() != tok_identifier)
-      return parseError<PrototypeAST>("function name", "in prototype");
-
-    std::string fnName(lexer.getId());
-    lexer.consume(tok_identifier);
-
-    if (lexer.getCurToken() != '(')
-      return parseError<PrototypeAST>("(", "in prototype");
-    lexer.consume(Token('('));
-
-    std::vector<std::unique_ptr<VariableExprAST>> args;
-    if (lexer.getCurToken() != ')') {
-      do {
-        std::string name(lexer.getId());
-        auto loc = lexer.getLastLocation();
-        lexer.consume(tok_identifier);
-        auto decl = std::make_unique<VariableExprAST>(std::move(loc), name);
-        args.push_back(std::move(decl));
-        if (lexer.getCurToken() != ',')
-          break;
-        lexer.consume(Token(','));
-        if (lexer.getCurToken() != tok_identifier)
-          return parseError<PrototypeAST>(
-              "identifier", "after ',' in function parameter list");
-      } while (true);
-    }
-    if (lexer.getCurToken() != ')')
-      return parseError<PrototypeAST>(")", "to end function prototype");
-
-    // success.
-    lexer.consume(Token(')'));
-    return std::make_unique<PrototypeAST>(std::move(loc), fnName,
-                                          std::move(args));
-  }
-
-  /// Parse a function definition, we expect a prototype initiated with the
-  /// `def` keyword, followed by a block containing a list of expressions.
-  ///
-  /// definition ::= prototype block
-  std::unique_ptr<FunctionAST> parseDefinition() {
-    auto proto = parsePrototype();
-    if (!proto)
-      return nullptr;
-
-    if (auto block = parseBlock())
-      return std::make_unique<FunctionAST>(std::move(proto), std::move(block));
-    return nullptr;
-  }
-
-  /// Get the precedence of the pending binary operator token.
-  int getTokPrecedence() {
-    if (!isascii(lexer.getCurToken()))
-      return -1;
-
-    // 1 is lowest precedence.
-    switch (static_cast<char>(lexer.getCurToken())) {
-    case '-':
-      return 20;
-    case '+':
-      return 20;
-    case '*':
-      return 40;
-    default:
-      return -1;
-    }
-  }
-
-  /// Helper function to signal errors while parsing, it takes an argument
-  /// indicating the expected token and another argument giving more context.
-  /// Location is retrieved from the lexer to enrich the error message.
-  template <typename R, typename T, typename U = const char *>
-  std::unique_ptr<R> parseError(T &&expected, U &&context = "") {
-    auto curToken = lexer.getCurToken();
-    llvm::errs() << "Parse error (" << lexer.getLastLocation().line << ", "
-                 << lexer.getLastLocation().col << "): expected '" << expected
-                 << "' " << context << " but has Token " << curToken;
-    if (isprint(curToken))
-      llvm::errs() << " '" << (char)curToken << "'";
-    llvm::errs() << "\n";
-    return nullptr;
-  }
-};
-
-} // namespace toy
-
-#endif // TOY_PARSER_H
diff --git a/mlir/examples/lisp/lispc.cpp b/mlir/examples/lisp/lispc.cpp
deleted file mode 100644
index 9f9920224a5296d..000000000000000
--- a/mlir/examples/lisp/lispc.cpp
+++ /dev/null
@@ -1,66 +0,0 @@
-//===- lispc.cpp - The Lisp Compiler ----------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// This file implements the entry point for the Lisp compiler.
-//
-//===----------------------------------------------------------------------===//
-
-#include "lisp/Parser.h"
-
-#include "llvm/ADT/StringRef.h"
-#include "llvm/Support/CommandLine.h"
-#include "llvm/Support/ErrorOr.h"
-#include "llvm/Support/MemoryBuffer.h"
-#include "llvm/Support/raw_ostream.h"
-
-using namespace lisp;
-namespace cl = llvm::cl;
-
-static cl::opt<std::string> inputFilename(cl::Positional,
-                                          cl::desc("<input lisp file>"),
-                                          cl::init("-"),
-                                          cl::value_desc("filename"));
-namespace {
-enum Action { None, DumpAST };
-} // namespace
-
-static cl::opt<enum Action>
-    emitAction("emit", cl::desc("Select the kind of output desired"),
-               cl::values(clEnumValN(DumpAST, "ast", "output the AST dump")));
-
-/// Returns a Lisp AST resulting from parsing the file or a nullptr on error.
-std::unique_ptr<lisp::ModuleAST> parseInputFile(llvm::StringRef filename) {
-  llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> fileOrErr =
-      llvm::MemoryBuffer::getFileOrSTDIN(filename);
-  if (std::error_code ec = fileOrErr.getError()) {
-    llvm::errs() << "Could not open input file: " << ec.message() << "\n";
-    return nullptr;
-  }
-  auto buffer = fileOrErr.get()->getBuffer();
-  LexerBuffer lexer(buffer.begin(), buffer.end(), std::string(filename));
-  Parser parser(lexer);
-  return parser.parseModule();
-}
-
-int main(int argc, char **argv) {
-  cl::ParseCommandLineOptions(argc, argv, "lisp compiler\n");
-
-  auto moduleAST = parseInputFile(inputFilename);
-  if (!moduleAST)
-    return 1;
-
-  switch (emitAction) {
-  case Action::DumpAST:
-    dump(*moduleAST);
-    return 0;
-  default:
-    llvm::errs() << "No action specified (parsing only?), use -emit=<action>\n";
-  }
-
-  return 0;
-}
diff --git a/mlir/examples/lisp/parser/AST.cpp b/mlir/examples/lisp/parser/AST.cpp
deleted file mode 100644
index 99bde6b8df5e525..000000000000000
--- a/mlir/examples/lisp/parser/AST.cpp
+++ /dev/null
@@ -1,234 +0,0 @@
-//===- AST.cpp - Helper for printing out the Lisp AST ----------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// This file implements the AST dump for the Lisp language.
-//
-//===----------------------------------------------------------------------===//
-
-#include "lisp/AST.h"
-
-#include "llvm/ADT/Twine.h"
-#include "llvm/ADT/TypeSwitch.h"
-#include "llvm/Support/raw_ostream.h"
-
-using namespace lisp;
-
-namespace {
-
-// RAII helper to manage increasing/decreasing the indentation as we traverse
-// the AST
-struct Indent {
-  Indent(int &level) : level(level) { ++level; }
-  ~Indent() { --level; }
-  int &level;
-};
-
-/// Helper class that implement the AST tree traversal and print the nodes along
-/// the way. The only data member is the current indentation level.
-class ASTDumper {
-public:
-  void dump(ModuleAST *node);
-
-private:
-  void dump(const VarType &type);
-  void dump(VarDeclExprAST *varDecl);
-  void dump(ExprAST *expr);
-  void dump(ExprASTList *exprList);
-  void dump(NumberExprAST *num);
-  void dump(LiteralExprAST *node);
-  void dump(VariableExprAST *node);
-  void dump(ReturnExprAST *node);
-  void dump(BinaryExprAST *node);
-  void dump(CallExprAST *node);
-  void dump(PrintExprAST *node);
-  void dump(PrototypeAST *node);
-  void dump(FunctionAST *node);
-
-  // Actually print spaces matching the current indentation level
-  void indent() {
-    for (int i = 0; i < curIndent; i++)
-      llvm::errs() << "  ";
-  }
-  int curIndent = 0;
-};
-
-} // namespace
-
-/// Return a formatted string for the location of any node
-template <typename T>
-static std::string loc(T *node) {
-  const auto &loc = node->loc();
-  return (llvm::Twine("@") + *loc.file + ":" + llvm::Twine(loc.line) + ":" +
-          llvm::Twine(loc.col))
-      .str();
-}
-
-// Helper Macro to bump the indentation level and print the leading spaces for
-// the current indentations
-#define INDENT()                                                               \
-  Indent level_(curIndent);                                                    \
-  indent();
-
-/// Dispatch to a generic expressions to the appropriate subclass using RTTI
-void ASTDumper::dump(ExprAST *expr) {
-  llvm::TypeSwitch<ExprAST *>(expr)
-      .Case<BinaryExprAST, CallExprAST, LiteralExprAST, NumberExprAST,
-            PrintExprAST, ReturnExprAST, VarDeclExprAST, VariableExprAST>(
-          [&](auto *node) { this->dump(node); })
-      .Default([&](ExprAST *) {
-        // No match, fallback to a generic message
-        INDENT();
-        llvm::errs() << "<unknown Expr, kind " << expr->getKind() << ">\n";
-      });
-}
-
-/// A variable declaration is printing the variable name, the type, and then
-/// recurse in the initializer value.
-void ASTDumper::dump(VarDeclExprAST *varDecl) {
-  INDENT();
-  llvm::errs() << "VarDecl " << varDecl->getName();
-  dump(varDecl->getType());
-  llvm::errs() << " " << loc(varDecl) << "\n";
-  dump(varDecl->getInitVal());
-}
-
-/// A "block", or a list of expression
-void ASTDumper::dump(ExprASTList *exprList) {
-  INDENT();
-  llvm::errs() << "Block {\n";
-  for (auto &expr : *exprList)
-    dump(expr.get());
-  indent();
-  llvm::errs() << "} // Block\n";
-}
-
-/// A literal number, just print the value.
-void ASTDumper::dump(NumberExprAST *num) {
-  INDENT();
-  llvm::errs() << num->getValue() << " " << loc(num) << "\n";
-}
-
-/// Helper to print recursively a literal. This handles nested array like:
-///    [ [ 1, 2 ], [ 3, 4 ] ]
-/// We print out such array with the dimensions spelled out at every level:
-///    <2,2>[<2>[ 1, 2 ], <2>[ 3, 4 ] ]
-void printLitHelper(ExprAST *litOrNum) {
-  // Inside a literal expression we can have either a number or another literal
-  if (auto *num = llvm::dyn_cast<NumberExprAST>(litOrNum)) {
-    llvm::errs() << num->getValue();
-    return;
-  }
-  auto *literal = llvm::cast<LiteralExprAST>(litOrNum);
-
-  // Print the dimension for this literal first
-  llvm::errs() << "<";
-  llvm::interleaveComma(literal->getDims(), llvm::errs());
-  llvm::errs() << ">";
-
-  // Now print the content, recursing on every element of the list
-  llvm::errs() << "[ ";
-  llvm::interleaveComma(literal->getValues(), llvm::errs(),
-                        [&](auto &elt) { printLitHelper(elt.get()); });
-  llvm::errs() << "]";
-}
-
-/// Print a literal, see the recursive helper above for the implementation.
-void ASTDumper::dump(LiteralExprAST *node) {
-  INDENT();
-  llvm::errs() << "Literal: ";
-  printLitHelper(node);
-  llvm::errs() << " " << loc(node) << "\n";
-}
-
-/// Print a variable reference (just a name).
-void ASTDumper::dump(VariableExprAST *node) {
-  INDENT();
-  llvm::errs() << "var: " << node->getName() << " " << loc(node) << "\n";
-}
-
-/// Return statement print the return and its (optional) argument.
-void ASTDumper::dump(ReturnExprAST *node) {
-  INDENT();
-  llvm::errs() << "Return\n";
-  if (node->getExpr().has_value())
-    return dump(*node->getExpr());
-  {
-    INDENT();
-    llvm::errs() << "(void)\n";
-  }
-}
-
-/// Print a binary operation, first the operator, then recurse into LHS and RHS.
-void ASTDumper::dump(BinaryExprAST *node) {
-  INDENT();
-  llvm::errs() << "BinOp: " << node->getOp() << " " << loc(node) << "\n";
-  dump(node->getLHS());
-  dump(node->getRHS());
-}
-
-/// Print a call expression, first the callee name and the list of args by
-/// recursing into each individual argument.
-void ASTDumper::dump(CallExprAST *node) {
-  INDENT();
-  llvm::errs() << "Call '" << node->getCallee() << "' [ " << loc(node) << "\n";
-  for (auto &arg : node->getArgs())
-    dump(arg.get());
-  indent();
-  llvm::errs() << "]\n";
-}
-
-/// Print a builtin print call, first the builtin name and then the argument.
-void ASTDumper::dump(PrintExprAST *node) {
-  INDENT();
-  llvm::errs() << "Print [ " << loc(node) << "\n";
-  dump(node->getArg());
-  indent();
-  llvm::errs() << "]\n";
-}
-
-/// Print type: only the shape is printed in between '<' and '>'
-void ASTDumper::dump(const VarType &type) {
-  llvm::errs() << "<";
-  llvm::interleaveComma(type.shape, llvm::errs());
-  llvm::errs() << ">";
-}
-
-/// Print a function prototype, first the function name, and then the list of
-/// parameters names.
-void ASTDumper::dump(PrototypeAST *node) {
-  INDENT();
-  llvm::errs() << "Proto '" << node->getName() << "' " << loc(node) << "\n";
-  indent();
-  llvm::errs() << "Params: [";
-  llvm::interleaveComma(node->getArgs(), llvm::errs(),
-                        [](auto &arg) { llvm::errs() << arg->getName(); });
-  llvm::errs() << "]\n";
-}
-
-/// Print a function, first the prototype and then the body.
-void ASTDumper::dump(FunctionAST *node) {
-  INDENT();
-  llvm::errs() << "Function \n";
-  dump(node->getProto());
-  dump(node->getBody());
-}
-
-/// Print a module, actually loop over the functions and print them in sequence.
-void ASTDumper::dump(ModuleAST *node) {
-  INDENT();
-  llvm::errs() << "Module:\n";
-  for (auto &f : *node)
-    dump(&f);
-}
-
-namespace lisp {
-
-// Public API
-void dump(ModuleAST &module) { ASTDumper().dump(&module); }
-
-} // namespace lisp

>From 4843ce884e2ae5bdcdc4f72fb6882fd211b56353 Mon Sep 17 00:00:00 2001
From: justinfargnoli <justinfargnoli at gmail.com>
Date: Sun, 8 Oct 2023 20:43:34 -0700
Subject: [PATCH 09/16] Revert "Add lisp example"

This reverts commit d7da0166d78aa30a3f3c66aaa963ff53c166ec90.
---
 mlir/examples/CMakeLists.txt | 1 -
 1 file changed, 1 deletion(-)

diff --git a/mlir/examples/CMakeLists.txt b/mlir/examples/CMakeLists.txt
index 734d5c83abef6cd..d256bf1a5cbb13d 100644
--- a/mlir/examples/CMakeLists.txt
+++ b/mlir/examples/CMakeLists.txt
@@ -1,4 +1,3 @@
 add_subdirectory(toy)
 add_subdirectory(transform)
 add_subdirectory(minimal-opt)
-add_subdirectory(lisp)

>From 6d66c1dd3783197bf513c7f17c228dbe6d4d3586 Mon Sep 17 00:00:00 2001
From: justinfargnoli <justinfargnoli at gmail.com>
Date: Tue, 10 Oct 2023 20:56:25 -0700
Subject: [PATCH 10/16] Update test

---
 .../parallel-loop-tiling-tile-size-check.mlir | 22 ++++++++++++++-----
 1 file changed, 17 insertions(+), 5 deletions(-)

diff --git a/mlir/test/Dialect/SCF/parallel-loop-tiling-tile-size-check.mlir b/mlir/test/Dialect/SCF/parallel-loop-tiling-tile-size-check.mlir
index bcbf79a80de2759..96b59f72176f8a1 100644
--- a/mlir/test/Dialect/SCF/parallel-loop-tiling-tile-size-check.mlir
+++ b/mlir/test/Dialect/SCF/parallel-loop-tiling-tile-size-check.mlir
@@ -1,8 +1,20 @@
-// RUN: mlir-opt %s -pass-pipeline='builtin.module(func.func(scf-parallel-loop-tiling{parallel-loop-tile-sizes=0}))' -split-input-file
+// RUN: mlir-opt %s -pass-pipeline='builtin.module(func.func(scf-parallel-loop-tiling{parallel-loop-tile-sizes=0}))' -split-input-file | FileCheck %s
 
-// XFAIL: *
-
-func.func @parallel_loop(%arg0 : index, %arg1 : index, %arg2 : index) {
-  scf.parallel (%i0) = (%arg0) to (%arg1) step (%arg2) {}
+func.func @parallel_loop(%arg0 : index, %arg1 : index, %arg2 : index,
+                    %arg3 : index, %arg4 : index, %arg5 : index,
+		    %A: memref<?x?xf32>, %B: memref<?x?xf32>,
+                    %C: memref<?x?xf32>, %result: memref<?x?xf32>) {
+  scf.parallel (%i0, %i1) = (%arg0, %arg1) to (%arg2, %arg3) step (%arg4, %arg5) {
+    %B_elem = memref.load %B[%i0, %i1] : memref<?x?xf32>
+    %C_elem = memref.load %C[%i0, %i1] : memref<?x?xf32>
+    %sum_elem = arith.addf %B_elem, %C_elem : f32
+    memref.store %sum_elem, %result[%i0, %i1] : memref<?x?xf32>
+  }
   return
 }
+
+// CHECK-LABEL:   func @parallel_loop(
+// CHECK-SAME:        [[ARG1:%.*]]: index, [[ARG2:%.*]]: index, [[ARG3:%.*]]: index, [[ARG4:%.*]]: index, [[ARG5:%.*]]: index, [[ARG6:%.*]]: index, [[ARG7:%.*]]: memref<?x?xf32>, [[ARG8:%.*]]: memref<?x?xf32>, [[ARG9:%.*]]: memref<?x?xf32>, [[ARG10:%.*]]: memref<?x?xf32>) {
+// CHECK:           scf.parallel ([[V1:%.*]], [[V2:%.*]]) = ([[ARG1]], [[ARG2]]) to ([[ARG3]], [[ARG4]]) step ([[ARG5]]
+// CHECK:           }
+// CHECK:           return
\ No newline at end of file

>From 8a92110c5f52f8cbc65ce1f7dd107a9e655c727f Mon Sep 17 00:00:00 2001
From: justinfargnoli <justinfargnoli at gmail.com>
Date: Tue, 10 Oct 2023 20:57:02 -0700
Subject: [PATCH 11/16] Use signalPassFailure() instead of assert()

---
 mlir/lib/Dialect/SCF/Transforms/ParallelLoopTiling.cpp | 10 ++++++----
 1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/mlir/lib/Dialect/SCF/Transforms/ParallelLoopTiling.cpp b/mlir/lib/Dialect/SCF/Transforms/ParallelLoopTiling.cpp
index 7e0e07670ef5221..fe247334282a78c 100644
--- a/mlir/lib/Dialect/SCF/Transforms/ParallelLoopTiling.cpp
+++ b/mlir/lib/Dialect/SCF/Transforms/ParallelLoopTiling.cpp
@@ -62,11 +62,10 @@ mlir::scf::tileParallelLoop(ParallelOp op, ArrayRef<int64_t> tileSizes,
   SmallVector<Value, 2> tileSizeConstants;
   tileSizeConstants.reserve(op.getUpperBound().size());
   for (size_t i = 0, end = op.getUpperBound().size(); i != end; ++i) {
-    if (i < tileSizes.size()) {
-      assert(tileSizes[i]);
+    if (i < tileSizes.size())
       tileSizeConstants.push_back(
           b.create<arith::ConstantIndexOp>(op.getLoc(), tileSizes[i]));
-    } else
+    else
       // Just pick 1 for the remaining dimensions.
       tileSizeConstants.push_back(
           b.create<arith::ConstantIndexOp>(op.getLoc(), 1));
@@ -111,7 +110,7 @@ mlir::scf::tileParallelLoop(ParallelOp op, ArrayRef<int64_t> tileSizes,
     // If the loop bounds and the loop step are constant and if the number of
     // loop iterations is an integer multiple of the tile size, we use a static
     // bound for the inner loop.
-    if (lowerBoundConstant && upperBoundConstant && stepConstant) {
+    if (lowerBoundConstant && upperBoundConstant && stepConstant && tileSize) {
       auto numIterations = llvm::divideCeil(upperBoundConstant.value() -
                                                 lowerBoundConstant.value(),
                                             stepConstant.value());
@@ -196,6 +195,9 @@ struct ParallelLoopTiling
   }
 
   void runOnOperation() override {
+    for (int64_t tileSize : tileSizes) 
+      if (!tileSize)
+        signalPassFailure();
     auto *parentOp = getOperation();
     SmallVector<ParallelOp, 2> innermostPloops;
     getInnermostParallelLoops(parentOp, innermostPloops);

>From 64953279ea982640274b2c8e5a4780f989e75468 Mon Sep 17 00:00:00 2001
From: justinfargnoli <justinfargnoli at gmail.com>
Date: Tue, 10 Oct 2023 21:01:13 -0700
Subject: [PATCH 12/16] Delete test

---
 .../parallel-loop-tiling-tile-size-check.mlir | 20 -------------------
 1 file changed, 20 deletions(-)
 delete mode 100644 mlir/test/Dialect/SCF/parallel-loop-tiling-tile-size-check.mlir

diff --git a/mlir/test/Dialect/SCF/parallel-loop-tiling-tile-size-check.mlir b/mlir/test/Dialect/SCF/parallel-loop-tiling-tile-size-check.mlir
deleted file mode 100644
index 96b59f72176f8a1..000000000000000
--- a/mlir/test/Dialect/SCF/parallel-loop-tiling-tile-size-check.mlir
+++ /dev/null
@@ -1,20 +0,0 @@
-// RUN: mlir-opt %s -pass-pipeline='builtin.module(func.func(scf-parallel-loop-tiling{parallel-loop-tile-sizes=0}))' -split-input-file | FileCheck %s
-
-func.func @parallel_loop(%arg0 : index, %arg1 : index, %arg2 : index,
-                    %arg3 : index, %arg4 : index, %arg5 : index,
-		    %A: memref<?x?xf32>, %B: memref<?x?xf32>,
-                    %C: memref<?x?xf32>, %result: memref<?x?xf32>) {
-  scf.parallel (%i0, %i1) = (%arg0, %arg1) to (%arg2, %arg3) step (%arg4, %arg5) {
-    %B_elem = memref.load %B[%i0, %i1] : memref<?x?xf32>
-    %C_elem = memref.load %C[%i0, %i1] : memref<?x?xf32>
-    %sum_elem = arith.addf %B_elem, %C_elem : f32
-    memref.store %sum_elem, %result[%i0, %i1] : memref<?x?xf32>
-  }
-  return
-}
-
-// CHECK-LABEL:   func @parallel_loop(
-// CHECK-SAME:        [[ARG1:%.*]]: index, [[ARG2:%.*]]: index, [[ARG3:%.*]]: index, [[ARG4:%.*]]: index, [[ARG5:%.*]]: index, [[ARG6:%.*]]: index, [[ARG7:%.*]]: memref<?x?xf32>, [[ARG8:%.*]]: memref<?x?xf32>, [[ARG9:%.*]]: memref<?x?xf32>, [[ARG10:%.*]]: memref<?x?xf32>) {
-// CHECK:           scf.parallel ([[V1:%.*]], [[V2:%.*]]) = ([[ARG1]], [[ARG2]]) to ([[ARG3]], [[ARG4]]) step ([[ARG5]]
-// CHECK:           }
-// CHECK:           return
\ No newline at end of file

>From 64a2ae55d7ec3598ffa9e2e9834475eddaac8136 Mon Sep 17 00:00:00 2001
From: justinfargnoli <justinfargnoli at gmail.com>
Date: Tue, 10 Oct 2023 21:01:31 -0700
Subject: [PATCH 13/16] Use == instead of !

---
 mlir/lib/Dialect/SCF/Transforms/ParallelLoopTiling.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/mlir/lib/Dialect/SCF/Transforms/ParallelLoopTiling.cpp b/mlir/lib/Dialect/SCF/Transforms/ParallelLoopTiling.cpp
index fe247334282a78c..be123f0e7225dab 100644
--- a/mlir/lib/Dialect/SCF/Transforms/ParallelLoopTiling.cpp
+++ b/mlir/lib/Dialect/SCF/Transforms/ParallelLoopTiling.cpp
@@ -196,7 +196,7 @@ struct ParallelLoopTiling
 
   void runOnOperation() override {
     for (int64_t tileSize : tileSizes) 
-      if (!tileSize)
+      if (tileSize == 0)
         signalPassFailure();
     auto *parentOp = getOperation();
     SmallVector<ParallelOp, 2> innermostPloops;

>From 26e79c1c56b40e82c2bfe20cb27f30e8e4ebd6f8 Mon Sep 17 00:00:00 2001
From: justinfargnoli <justinfargnoli at gmail.com>
Date: Tue, 10 Oct 2023 21:49:38 -0700
Subject: [PATCH 14/16] Use `auto`

---
 mlir/lib/Dialect/SCF/Transforms/ParallelLoopTiling.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/mlir/lib/Dialect/SCF/Transforms/ParallelLoopTiling.cpp b/mlir/lib/Dialect/SCF/Transforms/ParallelLoopTiling.cpp
index be123f0e7225dab..f97792e6ff3f15f 100644
--- a/mlir/lib/Dialect/SCF/Transforms/ParallelLoopTiling.cpp
+++ b/mlir/lib/Dialect/SCF/Transforms/ParallelLoopTiling.cpp
@@ -195,7 +195,7 @@ struct ParallelLoopTiling
   }
 
   void runOnOperation() override {
-    for (int64_t tileSize : tileSizes) 
+    for (auto tileSize : tileSizes)
       if (tileSize == 0)
         signalPassFailure();
     auto *parentOp = getOperation();

>From 04c9b8f0e6582c5547058b1debc8fd1b3cd2ae0e Mon Sep 17 00:00:00 2001
From: justinfargnoli <justinfargnoli at gmail.com>
Date: Wed, 11 Oct 2023 21:53:37 -0700
Subject: [PATCH 15/16] Refactor to use emitError

---
 mlir/lib/Dialect/SCF/Transforms/ParallelLoopTiling.cpp | 9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/mlir/lib/Dialect/SCF/Transforms/ParallelLoopTiling.cpp b/mlir/lib/Dialect/SCF/Transforms/ParallelLoopTiling.cpp
index f97792e6ff3f15f..fdc28060917fb26 100644
--- a/mlir/lib/Dialect/SCF/Transforms/ParallelLoopTiling.cpp
+++ b/mlir/lib/Dialect/SCF/Transforms/ParallelLoopTiling.cpp
@@ -110,7 +110,7 @@ mlir::scf::tileParallelLoop(ParallelOp op, ArrayRef<int64_t> tileSizes,
     // If the loop bounds and the loop step are constant and if the number of
     // loop iterations is an integer multiple of the tile size, we use a static
     // bound for the inner loop.
-    if (lowerBoundConstant && upperBoundConstant && stepConstant && tileSize) {
+    if (lowerBoundConstant && upperBoundConstant && stepConstant) {
       auto numIterations = llvm::divideCeil(upperBoundConstant.value() -
                                                 lowerBoundConstant.value(),
                                             stepConstant.value());
@@ -196,8 +196,11 @@ struct ParallelLoopTiling
 
   void runOnOperation() override {
     for (auto tileSize : tileSizes)
-      if (tileSize == 0)
-        signalPassFailure();
+      if (tileSize == 0) {
+        mlir::emitError(mlir::UnknownLoc::get(&Pass::getContext()),
+                        "tile size cannot be 0");
+        return signalPassFailure();
+      }
     auto *parentOp = getOperation();
     SmallVector<ParallelOp, 2> innermostPloops;
     getInnermostParallelLoops(parentOp, innermostPloops);

>From 8de77b6a2c48a50c6f4bf1e01c4ca66d6b989d3b Mon Sep 17 00:00:00 2001
From: justinfargnoli <justinfargnoli at gmail.com>
Date: Wed, 11 Oct 2023 22:04:03 -0700
Subject: [PATCH 16/16] Add regression test

---
 .../Dialect/SCF/parallel-loop-tiling-check-tile-size.mlir | 8 ++++++++
 1 file changed, 8 insertions(+)
 create mode 100644 mlir/test/Dialect/SCF/parallel-loop-tiling-check-tile-size.mlir

diff --git a/mlir/test/Dialect/SCF/parallel-loop-tiling-check-tile-size.mlir b/mlir/test/Dialect/SCF/parallel-loop-tiling-check-tile-size.mlir
new file mode 100644
index 000000000000000..92ff853296e3c6b
--- /dev/null
+++ b/mlir/test/Dialect/SCF/parallel-loop-tiling-check-tile-size.mlir
@@ -0,0 +1,8 @@
+// RUN: mlir-opt %s -pass-pipeline='builtin.module(func.func(scf-parallel-loop-tiling{parallel-loop-tile-sizes=0,0}))' -split-input-file -verify-diagnostics
+
+// XFAIL: *
+
+func.func @parallel_loop(%arg0 : index, %arg1 : index, %arg2 : index) {
+  scf.parallel (%i) = (%arg0) to (%arg1) step (%arg2) {}
+  return
+}



More information about the cfe-commits mailing list