diff options
author | David Greene <greened@obbligato.org> | 2009-05-14 22:38:31 +0000 |
---|---|---|
committer | David Greene <greened@obbligato.org> | 2009-05-14 22:38:31 +0000 |
commit | 5f9f9ba00b85eb19da2618f393e43a6a11b5d892 (patch) | |
tree | bd237c2d0cb6a5ec6c114294dfdb5bd049d1501a | |
parent | beb31a51f67f651c5fa3c5094a78266d04a697a5 (diff) | |
download | external_llvm-5f9f9ba00b85eb19da2618f393e43a6a11b5d892.zip external_llvm-5f9f9ba00b85eb19da2618f393e43a6a11b5d892.tar.gz external_llvm-5f9f9ba00b85eb19da2618f393e43a6a11b5d892.tar.bz2 |
Graduate LLVM to the big leagues by embedding a LISP processor into TableGen.
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
-rw-r--r-- | docs/TableGenFundamentals.html | 6 | ||||
-rw-r--r-- | test/TableGen/lisp.td | 21 | ||||
-rw-r--r-- | utils/TableGen/Record.cpp | 38 | ||||
-rw-r--r-- | utils/TableGen/Record.h | 10 | ||||
-rw-r--r-- | utils/TableGen/TGLexer.cpp | 3 | ||||
-rw-r--r-- | utils/TableGen/TGLexer.h | 2 | ||||
-rw-r--r-- | utils/TableGen/TGParser.cpp | 75 |
7 files changed, 149 insertions, 6 deletions
diff --git a/docs/TableGenFundamentals.html b/docs/TableGenFundamentals.html index 9607f9e..36798c8 100644 --- a/docs/TableGenFundamentals.html +++ b/docs/TableGenFundamentals.html @@ -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 index 0000000..3e392fd --- /dev/null +++ b/test/TableGen/lisp.td @@ -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"]>; diff --git a/utils/TableGen/Record.cpp b/utils/TableGen/Record.cpp index ade1702..ae2c2f3 100644 --- a/utils/TableGen/Record.cpp +++ b/utils/TableGen/Record.cpp @@ -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() + ")"; } diff --git a/utils/TableGen/Record.h b/utils/TableGen/Record.h index c37f6e6..c2549da 100644 --- a/utils/TableGen/Record.h +++ b/utils/TableGen/Record.h @@ -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; diff --git a/utils/TableGen/TGLexer.cpp b/utils/TableGen/TGLexer.cpp index 6215a72..faf1e75 100644 --- a/utils/TableGen/TGLexer.cpp +++ b/utils/TableGen/TGLexer.cpp @@ -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"); } diff --git a/utils/TableGen/TGLexer.h b/utils/TableGen/TGLexer.h index 3993e89..3d27e5e 100644 --- a/utils/TableGen/TGLexer.h +++ b/utils/TableGen/TGLexer.h @@ -46,7 +46,7 @@ namespace tgtok { // !keywords. XConcat, XSRA, XSRL, XSHL, XStrConcat, XNameConcat, XCast, XSubst, - XForEach, + XForEach, XCar, XCdr, XNull, // Integer value. IntVal, diff --git a/utils/TableGen/TGParser.cpp b/utils/TableGen/TGParser.cpp index bc5d65e..8ff25a6 100644 --- a/utils/TableGen/TGParser.cpp +++ b/utils/TableGen/TGParser.cpp @@ -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,11 +696,24 @@ 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) { TokError("expected '(' after unary operator"); @@ -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: |