Start transitioning towards using 'let X = y in' statements, instead of 'set X =...
[oota-llvm.git] / support / tools / TableGen / FileParser.y
index ab1819c554a94a0a46b04e551d5b4c755538233c..95dfb42ca92620eed990ee7692023ae5f6268864 100644 (file)
@@ -6,44 +6,46 @@
 
 %{
 #include "Record.h"
-#include <iostream>
+#include "Support/StringExtras.h"
 #include <algorithm>
-#include <string>
-#include <stdio.h>
+#include <cstdio>
 #define YYERROR_VERBOSE 1
 
 int yyerror(const char *ErrorMsg);
 int yylex();
-extern FILE *Filein;
 extern int Filelineno;
-int Fileparse();
 static Record *CurRec = 0;
 
 typedef std::pair<Record*, std::vector<Init*>*> SubClassRefTy;
 
-static std::vector<std::pair<std::pair<std::string, std::vector<unsigned>*>,
-                             Init*> > SetStack;
+struct LetRecord {
+  std::string Name;
+  std::vector<unsigned> Bits;
+  Init *Value;
+  bool HasBits;
+  LetRecord(const std::string &N, std::vector<unsigned> *B, Init *V)
+    : Name(N), Value(V), HasBits(B != 0) {
+    if (HasBits) Bits = *B;
+  }
+};
 
-void ParseFile() {
-  FILE *F = stdin;
+static std::vector<std::vector<LetRecord> > LetStack;
 
-  Filein = F;
-  Filelineno = 1;
-  Fileparse();
-  Filein = stdin;
-}
 
-static std::ostream &err() {
-  return std::cerr << "Parsing Line #" << Filelineno << ": ";
-}
+extern std::ostream &err();
 
 static void addValue(const RecordVal &RV) {
-  if (CurRec->getValue(RV.getName())) {
-    err() << "Value '" << RV.getName() << "' multiply defined!\n";
-    abort();
+  if (RecordVal *ERV = CurRec->getValue(RV.getName())) {
+    // The value already exists in the class, treat this as a set...
+    if (ERV->setValue(RV.getValue())) {
+      err() << "New definition of '" << RV.getName() << "' of type '"
+            << *RV.getType() << "' is incompatible with previous "
+            << "definition of type '" << *ERV->getType() << "'!\n";
+      abort();
+    }
+  } else {
+    CurRec->addValue(RV);
   }
-
-  CurRec->addValue(RV);
 }
 
 static void addSuperClass(Record *SC) {
@@ -160,20 +162,18 @@ static void addSubClass(Record *SC, const std::vector<Init*> &TemplateArgs) {
   RecTy                *Ty;
   Init                 *Initializer;
   std::vector<Init*>   *FieldList;
-  std::vector<Record*> *RecPtr;
   std::vector<unsigned>*BitList;
   Record               *Rec;
   SubClassRefTy        *SubClassRef;
   std::vector<SubClassRefTy> *SubClassList;
 };
 
-%token INT BIT STRING BITS LIST CLASS DEF FIELD SET IN
+%token INT BIT STRING BITS LIST CODE DAG CLASS DEF FIELD LET IN
 %token <IntVal>      INTVAL
-%token <StrVal>      ID STRVAL
+%token <StrVal>      ID STRVAL CODEFRAGMENT
 
 %type <Ty>           Type
-%type <RecPtr>       DefList DefListNE
-%type <Rec>          ClassInst DefInst Object ObjectBody ClassID DefID
+%type <Rec>          ClassInst DefInst Object ObjectBody ClassID
 
 %type <SubClassRef>  SubClassRef
 %type <SubClassList> ClassList ClassListNE
@@ -181,7 +181,7 @@ static void addSubClass(Record *SC, const std::vector<Init*> &TemplateArgs) {
 %type <Initializer>  Value OptValue
 %type <FieldList>    ValueList ValueListNE
 %type <BitList>      BitList OptBitList RBitList
-%type <StrVal>       Declaration
+%type <StrVal>       Declaration OptID
 
 %start File
 %%
@@ -195,15 +195,6 @@ ClassID : ID {
     delete $1;
   };
 
-DefID : ID {
-    $$ = Records.getDef(*$1);
-    if ($$ == 0) {
-      err() << "Couldn't find def '" << *$1 << "'!\n";
-      abort();
-    }
-    delete $1;
-  };
-
 
 // TableGen types...
 Type : STRING {                       // string type
@@ -214,8 +205,12 @@ Type : STRING {                       // string type
     $$ = new BitsRecTy($3);
   } | INT {                           // int type
     $$ = new IntRecTy();
-  } | LIST '<' ClassID '>' {          // list<x> type
+  } | LIST '<' Type '>'    {          // list<x> type
     $$ = new ListRecTy($3);
+  } | CODE {                          // code type
+    $$ = new CodeRecTy();
+  } | DAG {                           // dag type
+    $$ = new DagRecTy();
   } | ClassID {                       // Record Type
     $$ = new RecordRecTy($1);
   };
@@ -229,6 +224,9 @@ Value : INTVAL {
   } | STRVAL {
     $$ = new StringInit(*$1);
     delete $1;
+  } | CODEFRAGMENT {
+    $$ = new CodeInit(*$1);
+    delete $1;
   } | '?' {
     $$ = new UnsetInit();
   } | '{' ValueList '}' {
@@ -245,7 +243,7 @@ Value : INTVAL {
     $$ = Init;
     delete $2;
   } | ID {
-    if (const RecordVal *RV = CurRec->getValue(*$1)) {
+    if (const RecordVal *RV = (CurRec ? CurRec->getValue(*$1) : 0)) {
       $$ = new VarInit(*$1, RV->getType());
     } else if (Record *D = Records.getDef(*$1)) {
       $$ = new DefInit(D);
@@ -262,7 +260,7 @@ Value : INTVAL {
       abort();
     }
     delete $3;
-  } | '[' DefList ']' {
+  } | '[' ValueList ']' {
     $$ = new ListInit(*$2);
     delete $2;
   } | Value '.' ID {
@@ -274,19 +272,6 @@ Value : INTVAL {
     delete $3;
   };
 
-DefList : /*empty */ {
-    $$ = new std::vector<Record*>();
-  } | DefListNE {
-    $$ = $1;
-  };
-DefListNE : DefID {
-    $$ = new std::vector<Record*>();
-    $$->push_back($1);
-  } | DefListNE ',' DefID {
-    ($$=$1)->push_back($3);
-  };
-
-
 RBitList : INTVAL {
     $$ = new std::vector<unsigned>();
     $$->push_back($1);
@@ -355,7 +340,7 @@ Declaration : OptPrefix Type ID OptValue {
 
 BodyItem : Declaration ';' {
   delete $1;
-} | SET ID OptBitList '=' Value ';' {
+} | LET ID OptBitList '=' Value ';' {
   setValue(*$2, $3, $5);
   delete $2;
   delete $3;
@@ -398,22 +383,40 @@ DeclListNE : Declaration {
 TemplateArgList : '<' DeclListNE '>' {};
 OptTemplateArgList : /*empty*/ | TemplateArgList;
 
-ObjectBody : ID {
+OptID : ID { $$ = $1; } | /*empty*/ { $$ = new std::string(); };
+
+ObjectBody : OptID {
+           static unsigned AnonCounter = 0;
+           if ($1->empty())
+             *$1 = "anonymous."+utostr(AnonCounter++);
            CurRec = new Record(*$1);
            delete $1;
          } OptTemplateArgList ClassList {
            for (unsigned i = 0, e = $4->size(); i != e; ++i) {
             addSubClass((*$4)[i].first, *(*$4)[i].second);
-            delete (*$4)[i].second;  // Delete the template list
-          }
-           delete $4;
+             // Delete the template arg values for the class
+             delete (*$4)[i].second;
+           }
 
           // Process any variables on the set stack...
-          for (unsigned i = 0, e = SetStack.size(); i != e; ++i)
-            setValue(SetStack[i].first.first, SetStack[i].first.second,
-                     SetStack[i].second);
+          for (unsigned i = 0, e = LetStack.size(); i != e; ++i)
+             for (unsigned j = 0, e = LetStack[i].size(); j != e; ++j)
+               setValue(LetStack[i][j].Name,
+                        LetStack[i][j].HasBits ? &LetStack[i][j].Bits : 0,
+                        LetStack[i][j].Value);
          } Body {
   CurRec->resolveReferences();
+
+  // Now that all of the references have been resolved, we can delete template
+  // arguments for superclasses, so they don't pollute our record, and so that
+  // their names won't conflict with later uses of the name...
+  for (unsigned i = 0, e = $4->size(); i != e; ++i) {
+    Record *SuperClass = (*$4)[i].first;
+    for (unsigned i = 0, e = SuperClass->getTemplateArgs().size(); i != e; ++i)
+    CurRec->removeValue(SuperClass->getTemplateArgs()[i]);
+  }
+  delete $4;   // Delete the class list...
+
   $$ = CurRec;
   CurRec = 0;
 };
@@ -427,7 +430,12 @@ ClassInst : CLASS ObjectBody {
 };
 
 DefInst : DEF ObjectBody {
-  // TODO: If ObjectBody has template arguments, it's an error.
+  if (!$2->getTemplateArgs().empty()) {
+    err() << "Def '" << $2->getName()
+          << "' is not permitted to have template arguments!\n";
+    abort();
+  }
+  // If ObjectBody has template arguments, it's an error.
   if (Records.getDef($2->getName())) {
     err() << "Def '" << $2->getName() << "' already defined!\n";
     abort();
@@ -438,13 +446,22 @@ DefInst : DEF ObjectBody {
 
 Object : ClassInst | DefInst;
 
-// Support Set commands wrapping objects...
-Object : SET ID OptBitList '=' Value IN {
-            SetStack.push_back(std::make_pair(std::make_pair(*$2, $3), $5));
-           delete $2;
-          } '{' ObjectList '}' {
-           delete SetStack.back().first.second; // Delete OptBitList
-           SetStack.pop_back();
+LETItem : ID OptBitList '=' Value {
+  LetStack.back().push_back(LetRecord(*$1, $2, $4));
+  delete $1; delete $2;
+};
+
+LETList : LETItem | LETList ',' LETItem;
+
+// LETCommand - A 'LET' statement start...
+LETCommand : LET { LetStack.push_back(std::vector<LetRecord>()); } LETList IN;
+
+// Support Set commands wrapping objects... both with and without braces.
+Object : LETCommand '{' ObjectList '}' {
+    LetStack.pop_back();
+  }
+  | LETCommand Object {
+    LetStack.pop_back();
   };
 
 ObjectList : Object {} | ObjectList Object {};