Graduate LLVM to the big leagues by embedding a LISP processor into TableGen.
authorDavid Greene <greened@obbligato.org>
Thu, 14 May 2009 22:38:31 +0000 (22:38 +0000)
committerDavid Greene <greened@obbligato.org>
Thu, 14 May 2009 22:38:31 +0000 (22:38 +0000)
Ok, not really, but do support some common LISP functions:

* car
* cdr
* null

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@71805 91177308-0d34-0410-b5e6-96231b3b80d8

docs/TableGenFundamentals.html
test/TableGen/lisp.td [new file with mode: 0644]
utils/TableGen/Record.cpp
utils/TableGen/Record.h
utils/TableGen/TGLexer.cpp
utils/TableGen/TGLexer.h
utils/TableGen/TGParser.cpp

index 9607f9ea9ec7b55f9bef5a8670e0a068872f304b..36798c8b8b82d949cfb7d7c8e70e909763008460 100644 (file)
@@ -411,6 +411,12 @@ aborts with an error. </dd>
   <dd>For each member 'b' of dag or list 'a' apply operator 'c.'  'b' is a 
 dummy variable that should be declared as a member variable of an instantiated 
 class.  This operation is analogous to $(foreach) in GNU make.</dd>
+<dt><tt>!car(a)</tt></dt>
+  <dd>The first element of list 'a.'</dd>
+<dt><tt>!cdr(a)</tt></dt>
+  <dd>The 2nd-N elements of list 'a.'</dd>
+<dt><tt>!null(a)</tt></dt>
+  <dd>An integer {0,1} indicating whether list 'a' is empty.</dd>
 </dl>
 
 <p>Note that all of the values have rules specifying how they convert to values
diff --git a/test/TableGen/lisp.td b/test/TableGen/lisp.td
new file mode 100644 (file)
index 0000000..3e392fd
--- /dev/null
@@ -0,0 +1,21 @@
+// RUN: tblgen %s | grep {}
+
+class List<list<string> n> {
+  list<string> names = n;
+}
+
+class CAR<string e> {
+  string element = e;
+}
+
+class CDR<list<string> r, int n> {
+  list<string> rest = r;
+  int null = n;
+}
+
+class NameList<list<string> Names> :
+  List<Names>, CAR<!car(Names)>, CDR<!cdr(Names), !null(!cdr(Names))>;
+
+def Three : NameList<["Tom", "Dick", "Harry"]>;
+
+def One : NameList<["Jeffrey Sinclair"]>;
index ade17026fbfb2203fb6474a833c3451bed042e24..ae2c2f3ea407157c413e9693b180b28dbf4fc51a 100644 (file)
@@ -520,6 +520,41 @@ Init *UnOpInit::Fold(Record *CurRec, MultiClass *CurMultiClass) {
     }
     break;
   }
+  case CAR: {
+    ListInit *LHSl = dynamic_cast<ListInit*>(LHS);
+    if (LHSl) {
+      if (LHSl->getSize() == 0) {
+        assert(0 && "Empty list in car");
+        return 0;
+      }
+      return LHSl->getElement(0);
+    }
+    break;
+  }
+  case CDR: {
+    ListInit *LHSl = dynamic_cast<ListInit*>(LHS);
+    if (LHSl) {
+      if (LHSl->getSize() == 0) {
+        assert(0 && "Empty list in cdr");
+        return 0;
+      }
+      ListInit *Result = new ListInit(LHSl->begin()+1, LHSl->end());
+      return Result;
+    }
+    break;
+  }
+  case LNULL: {
+    ListInit *LHSl = dynamic_cast<ListInit*>(LHS);
+    if (LHSl) {
+      if (LHSl->getSize() == 0) {
+        return new IntInit(1);
+      }
+      else {
+        return new IntInit(0);
+      }
+    }
+    break;
+  }
   }
   return this;
 }
@@ -536,6 +571,9 @@ std::string UnOpInit::getAsString() const {
   std::string Result;
   switch (Opc) {
   case CAST: Result = "!cast<" + getType()->getAsString() + ">"; break;
+  case CAR: Result = "!car"; break;
+  case CDR: Result = "!cdr"; break;
+  case LNULL: Result = "!null"; break;
   }
   return Result + "(" + LHS->getAsString() + ")";
 }
index c37f6e620710c7cc256103c2912f1ff37f101ff7..c2549dab73a9b123a41bff4a72c363c8afb8fb61 100644 (file)
@@ -690,9 +690,14 @@ public:
 class ListInit : public Init {
   std::vector<Init*> Values;
 public:
+  typedef std::vector<Init*>::iterator       iterator;
+  typedef std::vector<Init*>::const_iterator const_iterator;
+
   explicit ListInit(std::vector<Init*> &Vs) {
     Values.swap(Vs);
   }
+  explicit ListInit(iterator Start, iterator End)
+    : Values(Start, End) {}
 
   unsigned getSize() const { return Values.size(); }
   Init *getElement(unsigned i) const {
@@ -717,9 +722,6 @@ public:
 
   virtual std::string getAsString() const;
 
-  typedef std::vector<Init*>::iterator       iterator;
-  typedef std::vector<Init*>::const_iterator const_iterator;
-
   inline iterator       begin()       { return Values.begin(); }
   inline const_iterator begin() const { return Values.begin(); }
   inline iterator       end  ()       { return Values.end();   }
@@ -761,7 +763,7 @@ public:
 ///
 class UnOpInit : public OpInit {
 public:
-  enum UnaryOp { CAST };
+  enum UnaryOp { CAST, CAR, CDR, LNULL };
 private:
   UnaryOp Opc;
   Init *LHS;
index 6215a7267fbdc469bf21fdba906dc994fda099d3..faf1e75a6849db3834528686362d7ee0dec7ef30 100644 (file)
@@ -450,6 +450,9 @@ tgtok::TokKind TGLexer::LexExclaim() {
   if (Len == 5 && !memcmp(Start, "subst", 5)) return tgtok::XSubst;
   if (Len == 7 && !memcmp(Start, "foreach", 7)) return tgtok::XForEach;
   if (Len == 4 && !memcmp(Start, "cast", 4)) return tgtok::XCast;
+  if (Len == 3 && !memcmp(Start, "car", 3)) return tgtok::XCar;
+  if (Len == 3 && !memcmp(Start, "cdr", 3)) return tgtok::XCdr;
+  if (Len == 4 && !memcmp(Start, "null", 4)) return tgtok::XNull;
 
   return ReturnError(Start-1, "Unknown operator");
 }
index 3993e89d64ef203662e8da3be4c913a6f338d2b9..3d27e5e8edb61b409fff9051286e1998fe38e7dc 100644 (file)
@@ -46,7 +46,7 @@ namespace tgtok {
     
     // !keywords.
     XConcat, XSRA, XSRL, XSHL, XStrConcat, XNameConcat, XCast, XSubst,
-    XForEach,
+    XForEach, XCar, XCdr, XNull,
 
     // Integer value.
     IntVal,
index bc5d65eea59008ce4fdaaa0d7624afd8e1de6f53..8ff25a6186bd502794fc3e68400e2cdc559df87c 100644 (file)
@@ -680,6 +680,9 @@ Init *TGParser::ParseOperation(Record *CurRec) {
     TokError("unknown operation");
     return 0;
     break;
+  case tgtok::XCar:
+  case tgtok::XCdr:
+  case tgtok::XNull:
   case tgtok::XCast: {  // Value ::= !unop '(' Value ')'
     UnOpInit::UnaryOp Code;
     RecTy *Type = 0;
@@ -693,10 +696,23 @@ Init *TGParser::ParseOperation(Record *CurRec) {
       Type = ParseOperatorType();
 
       if (Type == 0) {
-        TokError("did not get type for binary operator");
+        TokError("did not get type for unary operator");
         return 0;
       }
 
+      break;
+    case tgtok::XCar:
+      Lex.Lex();  // eat the operation
+      Code = UnOpInit::CAR;
+      break;
+    case tgtok::XCdr:
+      Lex.Lex();  // eat the operation
+      Code = UnOpInit::CDR;
+      break;
+    case tgtok::XNull:
+      Lex.Lex();  // eat the operation
+      Code = UnOpInit::LNULL;
+      Type = new IntRecTy;
       break;
     }
     if (Lex.getCode() != tgtok::l_paren) {
@@ -708,6 +724,60 @@ Init *TGParser::ParseOperation(Record *CurRec) {
     Init *LHS = ParseValue(CurRec);
     if (LHS == 0) return 0;
 
+    if (Code == UnOpInit::CAR
+        || Code == UnOpInit::CDR
+        || Code == UnOpInit::LNULL) {
+      ListInit *LHSl = dynamic_cast<ListInit*>(LHS);
+      TypedInit *LHSt = dynamic_cast<TypedInit*>(LHS);
+      if (LHSl == 0 && LHSt == 0) {
+        TokError("expected list type argument in unary operator");
+        return 0;
+      }
+      if (LHSt) {
+        ListRecTy *LType = dynamic_cast<ListRecTy*>(LHSt->getType());
+        if (LType == 0) {
+          TokError("expected list type argumnet in unary operator");
+          return 0;
+        }
+      }
+
+      if (Code == UnOpInit::CAR
+          || Code == UnOpInit::CDR) {
+        if (LHSl && LHSl->getSize() == 0) {
+          TokError("empty list argument in unary operator");
+          return 0;
+        }
+        if (LHSl) {
+          Init *Item = LHSl->getElement(0);
+          TypedInit *Itemt = dynamic_cast<TypedInit*>(Item);
+          if (Itemt == 0) {
+            TokError("untyped list element in unary operator");
+            return 0;
+          }
+          if (Code == UnOpInit::CAR) {
+            Type = Itemt->getType();
+          }
+          else {
+            Type = new ListRecTy(Itemt->getType());
+          }
+        }
+        else {
+          assert(LHSt && "expected list type argument in unary operator");
+          ListRecTy *LType = dynamic_cast<ListRecTy*>(LHSt->getType());
+          if (LType == 0) {
+            TokError("expected list type argumnet in unary operator");
+            return 0;
+          }
+          if (Code == UnOpInit::CAR) {
+            Type = LType->getElementType();
+          }
+          else {
+            Type = LType;
+          }
+        }
+      }
+    }
+
     if (Lex.getCode() != tgtok::r_paren) {
       TokError("expected ')' in unary operator");
       return 0;
@@ -1072,6 +1142,9 @@ Init *TGParser::ParseSimpleValue(Record *CurRec) {
     break;
   }
  
+  case tgtok::XCar:
+  case tgtok::XCdr:
+  case tgtok::XNull:
   case tgtok::XCast:  // Value ::= !unop '(' Value ')'
   case tgtok::XConcat:
   case tgtok::XSRA: