[llvm-commits] CVS: llvm/projects/Stacker/lib/compiler/Lexer.l Makefile README StackerCompiler.cpp StackerCompiler.h StackerParser.y

Chris Lattner lattner at cs.uiuc.edu
Sun Nov 23 11:54:10 PST 2003


Changes in directory llvm/projects/Stacker/lib/compiler:

Lexer.l added (r1.1)
Makefile added (r1.1)
README added (r1.1)
StackerCompiler.cpp added (r1.1)
StackerCompiler.h added (r1.1)
StackerParser.y added (r1.1)

---
Log message:

Initial stacker checkin


---
Diffs of the changes:  (+2417 -0)

Index: llvm/projects/Stacker/lib/compiler/Lexer.l
diff -c /dev/null llvm/projects/Stacker/lib/compiler/Lexer.l:1.1
*** /dev/null	Sun Nov 23 11:53:05 2003
--- llvm/projects/Stacker/lib/compiler/Lexer.l	Sun Nov 23 11:52:55 2003
***************
*** 0 ****
--- 1,234 ----
+ /*===-- Lexer.l - Scanner for Stacker language -----------------*- C++ -*--===//
+ // 
+ //                     The LLVM Compiler Infrastructure
+ //
+ // This file was developed by Reid Spencer and donated to the LLVM research 
+ // group and is distributed under the University of Illinois Open Source 
+ // License. See LICENSE.TXT for details.
+ // 
+ //===----------------------------------------------------------------------===//
+ //
+ //  This file implements the flex scanner for Stacker languages files.
+ //
+ //===----------------------------------------------------------------------===*/
+ 
+ %option prefix="Stacker"
+ %option yylineno
+ %option nostdinit
+ %option never-interactive
+ %option batch
+ %option noyywrap
+ %option nodefault
+ %option 8bit
+ %option outfile="Lexer.cpp"
+ %option ecs
+ %option noreject
+ %option noyymore
+ 
+ %{
+ 
+ #include "StackerCompiler.h"
+ #include "StackerParser.h"
+ 
+ /* Conversion of text ints to binary */
+ static uint64_t IntToVal(const char *Buffer) {
+   uint64_t Result = 0;
+   for (; *Buffer; Buffer++) {
+     uint64_t OldRes = Result;
+     Result *= 10;
+     Result += *Buffer-'0';
+     if (Result < OldRes)   // Uh, oh, overflow detected!!!
+       StackerCompiler::ThrowException("constant bigger than 64 bits detected!");
+   }
+   return Result;
+ }
+ 
+ /* Conversion of text hexadecimal ints to binary */
+ static uint64_t HexIntToVal(const char *Buffer) {
+   uint64_t Result = 0;
+   for (; *Buffer; ++Buffer) {
+     uint64_t OldRes = Result;
+     Result *= 16;
+     char C = *Buffer;
+     if (C >= '0' && C <= '9')
+       Result += C-'0';
+     else if (C >= 'A' && C <= 'F')
+       Result += C-'A'+10;
+     else if (C >= 'a' && C <= 'f')
+       Result += C-'a'+10;
+ 
+     if (Result < OldRes)   // Uh, oh, overflow detected!!!
+       StackerCompiler::ThrowException("constant bigger than 64 bits detected!");
+   }
+   return Result;
+ }
+ 
+ #define YY_NEVER_INTERACTIVE 1
+ %}
+ 
+ /* Comments start with a ; and go till end of line */
+ Comment1	[#].*$
+ /* You can also embed them in ( ... ) */
+ Comment2	\(.*\)
+ /* We ignore white space */
+ White		[ \t\n]
+ 
+ /* jdentifiers start with a % sign */
+ Identifier  	[A-Za-z][-A-Za-z0-9_]*
+ 
+ /* Strings can contain any character except " and \ */
+ String		\"[^\"]*\"
+ 
+ /* Positive and negative integer constants*/
+ PInteger	[+]?[0-9]+
+ NInteger	-[0-9]+
+ HexInteger 	0x[0-9A-Fa-f]+
+ 
+ /* Special Characters - name them to avoid flex confusion */
+ Semi 		[;]
+ Colon 		[:]
+ Less		\<
+ More		\>
+ LessEq		\<\=
+ MoreEq		\>\=
+ NotEq		\<\>
+ Equal		\=
+ Plus		\+
+ Minus		\-
+ Incr		\+\+
+ Decr		\-\-
+ Mult		\*
+ Div		\/
+ StarSlash	\*\/
+ LShift		\<\<
+ RShift		\>\>
+ InStr		\<s
+ InNum		\<d
+ InChar		\<c
+ OutStr		\>s
+ OutNum		\>d
+ OutChar		\>c
+ 
+ %%
+ 
+ {Comment1}	{ /* Ignore comments */ }
+ {Comment2}	{ /* Ignore comments */ }
+ 
+ {Colon}		{ return COLON; }
+ {Semi}		{ return SEMI; }
+ 
+ TRUE		{ return TRUE; }
+ FALSE		{ return FALSE; }
+ ON		{ return TRUE; }
+ OFF		{ return FALSE; }
+ {Less}		{ return LESS; }
+ LT		{ return LESS; }
+ {More}		{ return MORE; }
+ GT		{ return MORE; }
+ {LessEq}	{ return LESS_EQUAL; }
+ LE		{ return LESS_EQUAL; }
+ {MoreEq}	{ return MORE_EQUAL; }
+ GE		{ return MORE_EQUAL; }
+ {NotEq}		{ return NOT_EQUAL; }
+ NE		{ return NOT_EQUAL; }
+ {Equal}		{ return EQUAL; }
+ EQ		{ return EQUAL; }
+ 
+ {Plus}		{ return PLUS; }
+ {Minus}		{ return MINUS; }
+ {Incr}		{ return INCR; }
+ {Decr}		{ return DECR; }
+ {Mult}		{ return MULT; }
+ {Div}		{ return DIV; }
+ MOD		{ return MODULUS; }
+ NEG		{ return NEGATE; }
+ ABS		{ return ABS; }
+ MIN		{ return MIN; }
+ MAX		{ return MAX; }
+ {StarSlash}	{ return STAR_SLASH; }
+ 
+ AND		{ return AND; }
+ OR		{ return OR; }
+ XOR		{ return XOR; }
+ {LShift}	{ return LSHIFT; }
+ {RShift}	{ return RSHIFT; }
+ 
+ DROP		{ return DROP; }
+ NIP		{ return NIP; }
+ DUP		{ return DUP; }
+ SWAP		{ return SWAP; }
+ OVER		{ return OVER; }
+ PICK		{ return PICK; }
+ SELECT		{ return SELECT; }
+ ROT		{ return ROT; }
+ RROT		{ return RROT; }
+ ROLL		{ return ROLL; }
+ TUCK		{ return TUCK; }
+ DROP2		{ return DROP2; }
+ NIP2		{ return NIP2; }
+ DUP2		{ return DUP2; }
+ SWAP2		{ return SWAP2; }
+ OVER2		{ return OVER2; }
+ TUCK2		{ return TUCK2; }
+ ROT2		{ return ROT2; }
+ RROT2		{ return RROT2; }
+ 
+ MALLOC		{ return MALLOC; }
+ FREE		{ return FREE; }
+ GET		{ return GET; }
+ PUT		{ return PUT; }
+ 
+ IF		{ return IF; }
+ ELSE		{ return ELSE; }
+ ENDIF		{ return ENDIF; }
+ WHILE		{ return WHILE; }
+ END		{ return END; }
+ 
+ RECURSE		{ return RECURSE; }
+ RETURN		{ return RETURN; }
+ EXIT		{ return EXIT; }
+ FORWARD		{ return FORWARD; }
+ TAB		{ return TAB; }
+ SPACE		{ return SPACE; }
+ CR		{ return CR; }
+ 
+ {InStr}		{ return IN_STR; }
+ {InNum}		{ return IN_NUM; }
+ {InChar} 	{ return IN_CHAR; }
+ 
+ {OutStr}	{ return OUT_STR; }
+ {OutNum}	{ return OUT_NUM; }
+ {OutChar} 	{ return OUT_CHAR; }
+ 
+ MAIN		{ return MAIN; }
+ 
+ DUMP		{ return DUMP; }
+ 
+ !=		{ StackerCompiler::ThrowException(
+ 		  "You probably meant to use a <> instead of !=" ); }
+ 
+ ==		{ StackerCompiler::ThrowException(
+ 		  "You probably meant to use a single = .. this isn't C"); }
+ 
+ {PInteger}      { Stackerlval.IntegerVal = IntToVal(yytext); return INTEGER; }
+ {NInteger}      { uint64_t Val = IntToVal(yytext+1);
+ 		  // +1:  we have bigger negative range
+ 		  if (Val > (uint64_t)INT64_MAX+1)
+ 		    StackerCompiler::ThrowException(
+ 		    "Constant too large for signed 64 bits!");
+                   Stackerlval.IntegerVal = -Val; 
+ 		  return INTEGER; 
+                 }
+ {HexInteger} 	{ Stackerlval.IntegerVal = HexIntToVal(yytext+3); 
+                    return INTEGER;
+                 }
+ 
+ {String} 	{ yytext[strlen(yytext)-1] = 0;           // nuke end quote
+ 		  Stackerlval.StringVal = strdup(yytext+1);  // Nuke start quote
+ 		  return STRING;
+                 }
+ 
+ {Identifier}    { Stackerlval.StringVal = strdup(yytext); return IDENTIFIER; }
+ 
+ {White}         { /* Ignore whitespace */ }
+ %%


Index: llvm/projects/Stacker/lib/compiler/Makefile
diff -c /dev/null llvm/projects/Stacker/lib/compiler/Makefile:1.1
*** /dev/null	Sun Nov 23 11:53:05 2003
--- llvm/projects/Stacker/lib/compiler/Makefile	Sun Nov 23 11:52:55 2003
***************
*** 0 ****
--- 1,21 ----
+ ##===- projects/sample/lib/sample/Makefile -----------------*- Makefile -*-===##
+ 
+ #
+ # Indicate where we are relative to the top of the source tree.
+ #
+ LEVEL=../../../..
+ 
+ #
+ # Give the name of a library.  This will build a dynamic version.
+ #
+ SHARED_LIBRARY=1
+ LIBRARYNAME=stkr_compiler
+ 
+ #
+ # Include Makefile.common so we know what to do.
+ #
+ include $(LEVEL)/Makefile.common
+ 
+ ifdef PARSE_DEBUG
+ INCLUDES += -DPARSE_DEBUG
+ endif


Index: llvm/projects/Stacker/lib/compiler/README
diff -c /dev/null llvm/projects/Stacker/lib/compiler/README:1.1
*** /dev/null	Sun Nov 23 11:53:05 2003
--- llvm/projects/Stacker/lib/compiler/README	Sun Nov 23 11:52:55 2003
***************
*** 0 ****
--- 1,20 ----
+ This directory contains a sample language front end for LLVM.
+ 
+ It is a *very* simple/crude implementation of FORTH. It has many
+ deficiencies but provides enough basics to give you an idea of 
+ what programming a new language front end for LLVM  looks like.
+ 
+ To keep things simple, Stacker has the following limitations:
+ 1. Only a single, global stack is manipulated.
+ 2. There is no interpretation, everything is compiled.
+ 3. There's no type/bounds checking .. you're on your own.
+ 4. There's no floating point support.
+ 5. Only stdin can be read. Only stdout can be written. No other 
+    file I/O is supported.
+ 
+ As such, this isn't a very useful language for anything other than
+ the most trivial of programs. It is, however, a good learning tool
+ (for both the author and the student).
+ 
+ Reid Spencer
+ 16 November 2003


Index: llvm/projects/Stacker/lib/compiler/StackerCompiler.cpp
diff -c /dev/null llvm/projects/Stacker/lib/compiler/StackerCompiler.cpp:1.1
*** /dev/null	Sun Nov 23 11:53:05 2003
--- llvm/projects/Stacker/lib/compiler/StackerCompiler.cpp	Sun Nov 23 11:52:55 2003
***************
*** 0 ****
--- 1,1728 ----
+ //===-- StackerCompiler.cpp - Parser for llvm assembly files ----*- C++ -*-===//
+ // 
+ //                     The LLVM Compiler Infrastructure
+ //
+ // This file was developed by Reid Spencer and donated to the LLVM research 
+ // group and is distributed under the University of Illinois Open Source 
+ // License. See LICENSE.TXT for details.
+ // 
+ //===----------------------------------------------------------------------===//
+ //
+ //  This file implements the compiler for the "Stacker" language.
+ //
+ //===----------------------------------------------------------------------===//
+ 
+ //===----------------------------------------------------------------------===//
+ //            Globasl - Global variables we use 
+ //===----------------------------------------------------------------------===//
+ 
+ #include <llvm/Analysis/Verifier.h>
+ #include <llvm/iMemory.h>
+ #include <llvm/iOperators.h>
+ #include <llvm/iOther.h>
+ #include <llvm/iTerminators.h>
+ #include <Support/Statistic.h>
+ #include "StackerCompiler.h"
+ #include "StackerParser.h"
+ #include <string>
+ 
+ // Lexer/Parser defined variables and functions
+ extern std::FILE *Stackerin;
+ extern int Stackerlineno;
+ extern char* Stackertext;
+ extern int Stackerleng;
+ extern int Stackerparse();
+ 
+ StackerCompiler* StackerCompiler::TheInstance = 0;
+ 
+ static Statistic<> NumDefinitions(
+ 	"numdefs","The # of definitions encoutered while compiling Stacker");
+ 
+ StackerCompiler::StackerCompiler()
+     : CurFilename("")
+     , TheModule(0)
+     , TheFunction(0)
+     , DefinitionType(0)
+     , TheStack(0)
+     , TheIndex(0)
+     , TheScanf(0)
+     , ThePrintf(0)
+     , TheExit(0)
+     , StrFormat(0)
+     , NumFormat(0)
+     , ChrFormat(0)
+     , InStrFormat(0)
+     , InNumFormat(0)
+     , InChrFormat(0)
+     , Zero(0)
+     , One(0)
+     , Two(0)
+     , Three(0)
+     , Four(0)
+     , Five(0)
+     , IZero(0)
+     , IOne(0)
+     , ITwo(0)
+     , no_arguments()
+     , echo(false)
+     , stack_size(256)
+     , stack_type(0)
+ {
+ }
+ 
+ StackerCompiler::~StackerCompiler()
+ {
+     // delete TheModule; << don't do this! 
+     // TheModule is passed to caller of the compile() method .. its their 
+     // problem.  Likewise for the other allocated objects (which become part 
+     // of TheModule.
+     TheModule = 0;
+     DefinitionType = 0;
+     TheStack = 0;
+     TheIndex = 0;
+ }
+ 
+ Module*
+ StackerCompiler::compile(
+     const std::string& filename,
+     bool should_echo,
+     size_t the_stack_size
+ )
+ {
+     // TODO: Provide a global lock to protect the singled-threaded compiler
+     // and its global variables. Should be in guard object on the stack so
+     // that its destructor causes lock to be released (multiple exits from
+     // this function).
+ 
+     // Assign parameters
+     CurFilename = filename;
+     echo = should_echo;
+     stack_size = the_stack_size;
+ 
+     /// Default the file to read
+     FILE *F = stdin;
+ 
+     ///
+     if (filename != "-") 
+     {
+ 	F = fopen(filename.c_str(), "r");
+ 
+ 	if (F == 0)
+ 	{
+ 	    throw ParseException(filename, 
+ 		"Could not open file '" + filename + "'");
+ 	}
+     }
+ 
+     Module *Result;
+     try 
+     {
+ 	// Create the module we'll return
+ 	TheModule = new Module( CurFilename );
+ 
+ 	// Create a type to represent the stack. This is the same as the LLVM 
+ 	// Assembly type [ 256 x int ]
+ 	stack_type = ArrayType::get( Type::IntTy, stack_size );
+ 
+ 	// Create a global variable for the stack. Note the use of appending 
+ 	// linkage linkage so that multiple modules will make the stack larger. 
+ 	// Also note that the last argument causes the global to be inserted 
+ 	// automatically into the module.
+ 	TheStack = new GlobalVariable( 
+ 	    /*type=*/ stack_type, 
+ 	    /*isConstant=*/ false, 
+ 	    /*Linkage=*/ GlobalValue::AppendingLinkage, 
+ 	    /*initializer=*/0, 
+ 	    /*name=*/ "_stack_",
+ 	    /*parent=*/ TheModule 
+ 	);
+ 
+ 	// Create a global variable for indexing into the stack. Note the use 
+ 	// of LinkOnce linkage. Only one copy of _index_ will be retained 
+ 	// after linking
+ 	TheIndex = new GlobalVariable( 
+ 	    /*type=*/Type::LongTy, 
+ 	    /*isConstant=*/false,
+ 	    /*Linkage=*/GlobalValue::LinkOnceLinkage, 
+ 	    /*initializer=*/0, 
+ 	    /*name=*/"_index_",
+ 	    /*parent=*/TheModule
+ 	);
+ 
+ 	// Create a function prototype for definitions. No parameters, no 
+ 	// result.  This is used below any time a function is created.
+ 	std::vector<const Type*> params; // No parameters
+ 	DefinitionType = FunctionType::get( Type::VoidTy, params, false );
+ 
+ 	// Create a function for printf(3)
+ 	params.push_back( PointerType::get( Type::SByteTy ) );
+ 	FunctionType* printf_type = 
+ 	    FunctionType::get( Type::IntTy, params, true );
+ 	ThePrintf = new Function( 
+ 	    printf_type, GlobalValue::ExternalLinkage, "printf", TheModule);
+ 
+ 	// Create a function for scanf(3)
+ 	TheScanf = new Function( 
+ 	    printf_type, GlobalValue::ExternalLinkage, "scanf", TheModule);
+ 
+ 	// Create a function for exit(3)
+ 	params.clear();
+ 	params.push_back( Type::IntTy );
+ 	FunctionType* exit_type = 
+ 	    FunctionType::get( Type::VoidTy, params, false );
+ 	TheExit = new Function( 
+ 	    exit_type, GlobalValue::ExternalLinkage, "exit", TheModule);
+ 
+ 	ConstantArray* str_format = ConstantArray::get("%s");
+ 	StrFormat = new GlobalVariable( 
+ 	    /*type=*/ArrayType::get( Type::SByteTy,  3 ),
+ 	    /*isConstant=*/true,
+ 	    /*Linkage=*/GlobalValue::LinkOnceLinkage, 
+ 	    /*initializer=*/str_format, 
+ 	    /*name=*/"_str_format_",
+ 	    /*parent=*/TheModule
+ 	);
+ 
+ 	ConstantArray* in_str_format = ConstantArray::get(" %as");
+ 	InStrFormat = new GlobalVariable( 
+ 	    /*type=*/ArrayType::get( Type::SByteTy,  5 ),
+ 	    /*isConstant=*/true,
+ 	    /*Linkage=*/GlobalValue::LinkOnceLinkage, 
+ 	    /*initializer=*/in_str_format, 
+ 	    /*name=*/"_in_str_format_",
+ 	    /*parent=*/TheModule
+ 	);
+ 
+ 	ConstantArray* num_format = ConstantArray::get("%d");
+ 	NumFormat = new GlobalVariable( 
+ 	    /*type=*/ArrayType::get( Type::SByteTy,  3 ),
+ 	    /*isConstant=*/true,
+ 	    /*Linkage=*/GlobalValue::LinkOnceLinkage, 
+ 	    /*initializer=*/num_format, 
+ 	    /*name=*/"_num_format_",
+ 	    /*parent=*/TheModule
+ 	);
+ 
+ 	ConstantArray* in_num_format = ConstantArray::get(" %d");
+ 	InNumFormat = new GlobalVariable( 
+ 	    /*type=*/ArrayType::get( Type::SByteTy,  4 ),
+ 	    /*isConstant=*/true,
+ 	    /*Linkage=*/GlobalValue::LinkOnceLinkage, 
+ 	    /*initializer=*/in_num_format, 
+ 	    /*name=*/"_in_num_format_",
+ 	    /*parent=*/TheModule
+ 	);
+ 
+ 	ConstantArray* chr_format = ConstantArray::get("%c");
+ 	ChrFormat = new GlobalVariable( 
+ 	    /*type=*/ArrayType::get( Type::SByteTy,  3 ),
+ 	    /*isConstant=*/true,
+ 	    /*Linkage=*/GlobalValue::LinkOnceLinkage, 
+ 	    /*initializer=*/chr_format, 
+ 	    /*name=*/"_chr_format_",
+ 	    /*parent=*/TheModule
+ 	);
+ 
+ 	ConstantArray* in_chr_format = ConstantArray::get(" %c");
+ 	InChrFormat = new GlobalVariable( 
+ 	    /*type=*/ArrayType::get( Type::SByteTy,  4 ),
+ 	    /*isConstant=*/true,
+ 	    /*Linkage=*/GlobalValue::LinkOnceLinkage, 
+ 	    /*initializer=*/in_chr_format, 
+ 	    /*name=*/"_in_chr_format_",
+ 	    /*parent=*/TheModule
+ 	);
+ 
+ 	// Get some constants so we aren't always creating them
+ 	Zero = ConstantInt::get( Type::LongTy, 0 );
+ 	One = ConstantInt::get( Type::LongTy, 1 );
+ 	Two = ConstantInt::get( Type::LongTy, 2 );
+ 	Three = ConstantInt::get( Type::LongTy, 3 );
+ 	Four = ConstantInt::get( Type::LongTy, 4 );
+ 	Five = ConstantInt::get( Type::LongTy, 5 );
+ 	IZero = ConstantInt::get( Type::IntTy, 0 );
+ 	IOne = ConstantInt::get( Type::IntTy, 1 );
+ 	ITwo = ConstantInt::get( Type::IntTy, 2 );
+ 
+ 	// Reset the current line number
+ 	Stackerlineno = 1;    
+ 
+ 	// Reset the parser's input to F
+ 	Stackerin = F;		// Set the input file.
+ 
+ 	// Let the parse know about this instance
+ 	TheInstance = this;
+ 
+ 	// Parse the file. The parser (see StackParser.y) will call back to 
+ 	// the StackCompiler via the "handle*" methods 
+ 	Stackerparse(); 
+ 
+ 	// Avoid potential illegal use (TheInstance might be on the stack)
+ 	TheInstance = 0;
+ 
+     } catch (...) {
+ 	if (F != stdin) fclose(F);      // Make sure to close file descriptor 
+ 	throw;                          // if an exception is thrown
+     }
+ 
+     // Close the file
+     if (F != stdin) fclose(F);
+     
+     // Return the compiled module to the caller
+     return TheModule;
+ }
+ 
+ //===----------------------------------------------------------------------===//
+ //            Internal Functions, used by handleXXX below.
+ //            These represent the basic stack operations.
+ //===----------------------------------------------------------------------===//
+ 
+ Instruction*
+ StackerCompiler::incr_stack_index( BasicBlock* bb, Value* ival = 0 )
+ {
+     // Load the value from the TheIndex
+     LoadInst* loadop = new LoadInst( TheIndex );
+     bb->getInstList().push_back( loadop );
+ 
+     // Increment the loaded index value
+     if ( ival == 0 ) ival = One;
+     CastInst* caster = new CastInst( ival, Type::LongTy );
+     bb->getInstList().push_back( caster );
+     BinaryOperator* addop = BinaryOperator::create( Instruction::Add, 
+ 	    loadop, caster);
+     bb->getInstList().push_back( addop );
+ 
+     // Store the incremented value
+     StoreInst* storeop = new StoreInst( addop, TheIndex );
+     bb->getInstList().push_back( storeop );
+     return storeop;
+ }
+ 
+ Instruction*
+ StackerCompiler::decr_stack_index( BasicBlock* bb, Value* ival = 0 )
+ {
+     // Load the value from the TheIndex
+     LoadInst* loadop = new LoadInst( TheIndex );
+     bb->getInstList().push_back( loadop );
+ 
+     // Decrement the loaded index value
+     if ( ival == 0 ) ival = One;
+     CastInst* caster = new CastInst( ival, Type::LongTy );
+     bb->getInstList().push_back( caster );
+     BinaryOperator* subop = BinaryOperator::create( Instruction::Sub, 
+ 	    loadop, caster);
+     bb->getInstList().push_back( subop );
+ 
+     // Store the incremented value
+     StoreInst* storeop = new StoreInst( subop, TheIndex );
+     bb->getInstList().push_back( storeop );
+ 
+     return storeop;
+ }
+ 
+ Instruction*
+ StackerCompiler::get_stack_pointer( BasicBlock* bb, Value* index = 0 )
+ {
+     // Load the value of the Stack Index 
+     LoadInst* loadop = new LoadInst( TheIndex );
+     bb->getInstList().push_back( loadop );
+ 
+     // Index into the stack to get its address. NOTE the use of two
+     // elements in this vector. The first de-references the pointer that
+     // "TheStack" represents. The second indexes into the pointed to array.
+     // Think of the first index as getting the address of the 0th element
+     // of the array.
+     std::vector<Value*> indexVec;
+     indexVec.push_back( Zero );
+ 
+     if ( index == 0 )
+     {
+ 	indexVec.push_back(loadop);	
+     }
+     else
+     {
+ 	CastInst* caster = new CastInst( index, Type::LongTy );
+ 	bb->getInstList().push_back( caster );
+ 	BinaryOperator* subop = BinaryOperator::create( 
+ 	    Instruction::Sub, loadop, caster );
+ 	bb->getInstList().push_back( subop );
+ 	indexVec.push_back(subop);
+     }
+ 
+     // Get the address of the indexed stack element
+     GetElementPtrInst* gep = new GetElementPtrInst( TheStack, indexVec );
+     bb->getInstList().push_back( gep );		// Put GEP in Block
+ 
+     return gep;
+ }
+ 
+ Instruction*
+ StackerCompiler::push_value( BasicBlock* bb, Value* val )
+ {
+     // Get location of 
+     incr_stack_index(bb);
+ 
+     // Get the stack pointer
+     GetElementPtrInst* gep = cast<GetElementPtrInst>( 
+ 	    get_stack_pointer( bb ) );
+ 
+     // Cast the value to an integer .. hopefully it works
+     CastInst* cast_inst = new CastInst( val, Type::IntTy );
+     bb->getInstList().push_back( cast_inst );
+ 
+     // Store the value
+     StoreInst* storeop = new StoreInst( cast_inst, gep );
+     bb->getInstList().push_back( storeop );
+ 
+     return storeop;
+ }
+ 
+ Instruction*
+ StackerCompiler::push_integer(BasicBlock* bb, int32_t value )
+ {
+     // Just push a constant integer value
+     return push_value( bb, ConstantSInt::get( Type::IntTy, value ) );
+ }
+ 
+ Instruction*
+ StackerCompiler::pop_integer( BasicBlock*bb )
+ {
+     // Get the stack pointer
+     GetElementPtrInst* gep = cast<GetElementPtrInst>(
+ 	get_stack_pointer( bb ));
+ 
+     // Load the value
+     LoadInst* load_inst = new LoadInst( gep );
+     bb->getInstList().push_back( load_inst );
+ 
+     // Decrement the stack index
+     decr_stack_index( bb );
+ 
+     // Return the value
+     return load_inst;
+ }
+ 
+ Instruction*
+ StackerCompiler::push_string( BasicBlock* bb, const char* value )
+ {
+     // Get length of the string
+     size_t len = strlen( value );
+ 
+     // Create a type for the string constant. Length is +1 for 
+     // the terminating 0.
+     ArrayType* char_array = ArrayType::get( Type::SByteTy, len + 1 );
+ 
+     // Create an initializer for the value
+     ConstantArray* initVal = ConstantArray::get( value );
+ 
+     // Create an internal linkage global variable to hold the constant.
+     GlobalVariable* strconst = new GlobalVariable( 
+ 	char_array, 
+ 	/*isConstant=*/true, 
+ 	GlobalValue::InternalLinkage, 
+ 	/*initializer=*/initVal,
+ 	"",
+ 	TheModule
+     );
+ 
+     // Push the casted value
+     return push_value( bb, strconst );
+ }
+ 
+ Instruction*
+ StackerCompiler::pop_string( BasicBlock* bb )
+ {
+     // Get location of stack pointer
+     GetElementPtrInst* gep = cast<GetElementPtrInst>(
+ 	get_stack_pointer( bb ));
+ 
+     // Load the value from the stack
+     LoadInst* loader = new LoadInst( gep );
+     bb->getInstList().push_back( loader );
+ 
+     // Cast the integer to a sbyte*
+     CastInst* caster = new CastInst( loader, PointerType::get(Type::SByteTy) );
+     bb->getInstList().push_back( caster );
+ 
+     // Decrement stack index
+     decr_stack_index( bb );
+ 
+     // Return the value
+     return caster;
+ }
+ 
+ Instruction*
+ StackerCompiler::replace_top( BasicBlock* bb, Value* new_top, Value* index = 0 )
+ {
+     // Get the stack pointer
+     GetElementPtrInst* gep = cast<GetElementPtrInst>(
+ 	    get_stack_pointer( bb, index ));
+     
+     // Store the value there
+     StoreInst* store_inst = new StoreInst( new_top, gep );
+     bb->getInstList().push_back( store_inst );
+ 
+     // Return the value
+     return store_inst;
+ }
+ 
+ Instruction*
+ StackerCompiler::stack_top( BasicBlock* bb, Value* index = 0 )
+ {
+     // Get the stack pointer
+     GetElementPtrInst* gep = cast<GetElementPtrInst>(
+ 	get_stack_pointer( bb, index ));
+ 
+     // Load the value
+     LoadInst* load_inst = new LoadInst( gep );
+     bb->getInstList().push_back( load_inst );
+ 
+     // Return the value
+     return load_inst;
+ }
+ 
+ Instruction*
+ StackerCompiler::stack_top_string( BasicBlock* bb, Value* index = 0 )
+ {
+     // Get location of stack pointer
+     GetElementPtrInst* gep = cast<GetElementPtrInst>(
+ 	get_stack_pointer( bb, index ));
+ 
+     // Load the value from the stack
+     LoadInst* loader = new LoadInst( gep );
+     bb->getInstList().push_back( loader );
+ 
+     // Cast the integer to a sbyte*
+     CastInst* caster = new CastInst( loader, PointerType::get(Type::SByteTy) );
+     bb->getInstList().push_back( caster );
+ 
+     // Return the value
+     return caster;
+ }
+ 
+ static void
+ add_block( Function*f, BasicBlock* bb )
+ {
+     if ( ! f->empty() && f->back().getTerminator() == 0 )
+     {
+ 	BranchInst* branch = new BranchInst(bb);
+ 	f->back().getInstList().push_back( branch );
+     }
+     f->getBasicBlockList().push_back( bb );
+ }
+ 
+ 
+ //===----------------------------------------------------------------------===//
+ //            handleXXX - Handle semantics of parser productions
+ //===----------------------------------------------------------------------===//
+ 
+ Module*
+ StackerCompiler::handle_module_start( )
+ {
+     // Return the newly created module
+     return TheModule;
+ }
+ 
+ Module* 
+ StackerCompiler::handle_module_end( Module* mod )
+ {
+     // Return the module.
+     return mod;
+ }
+ 
+ Module*
+ StackerCompiler::handle_definition_list_start()
+ {
+     return TheModule;
+ }
+ 
+ Module* 
+ StackerCompiler::handle_definition_list_end( Module* mod, Function* definition )
+ {
+     if ( ! definition->empty() )
+     {
+ 	BasicBlock& last_block = definition->back();
+ 	if ( last_block.getTerminator() == 0 )
+ 	{
+ 	    last_block.getInstList().push_back( new ReturnInst() );
+ 	}
+     }
+     // Insert the definition into the module
+     mod->getFunctionList().push_back( definition );
+ 
+     // Bump our (sample) statistic.
+     ++NumDefinitions;
+     return mod;
+ }
+ 
+ Function*
+ StackerCompiler::handle_main_definition( Function* func )
+ {
+     // Set the name of the function defined as the Stacker main
+     func->setName( "_MAIN_");
+ 
+     // Create the actual main for the runtime system.
+     //std::vector<const Type*> params; // No parameters
+     //FunctionType* main_type = FunctionType::get( Type::IntTy, params, false );
+     Function* SystemMain = new Function(
+ 	DefinitionType, 
+ 	GlobalValue::ExternalLinkage,
+ 	"main", TheModule);
+ 
+     // Create a basic block that just calls the STACKERMAIN function. Note
+     // that the basic block is automatically inserted into the end of SystemMain
+     BasicBlock* bb = new BasicBlock( (echo?"main":"a"), SystemMain ) ;
+     bb->getInstList().push_back( new CallInst( func, no_arguments) );
+     bb->getInstList().push_back( new ReturnInst() ); 
+ 
+     // Turn "_stack_" into an initialized variable since this is the main
+     // module. This causes it to not be "external" but defined in this module.
+     TheStack->setInitializer( Constant::getNullValue(stack_type) );
+ 
+     // Turn "_index_" into an intialized variable for the same reason.
+     TheIndex->setInitializer( Constant::getNullValue(Type::LongTy) );
+     return func;
+ }
+ 
+ Function* 
+ StackerCompiler::handle_forward( char * name )
+ {
+     // Just create a placeholder function
+     Function* the_function = new Function ( 
+ 	DefinitionType, 
+ 	GlobalValue::ExternalLinkage, 
+ 	name ); 
+     assert( the_function->isExternal() );
+ 
+     free( name );
+     return the_function;
+ }
+ 
+ Function* 
+ StackerCompiler::handle_definition( char * name, Function* f )
+ {
+     // Look up the function name in the module to see if it was forward
+     // declared.
+     Function* existing_function = TheModule->getNamedFunction( name );
+ 
+ #if 0
+     // If the function already exists...
+     if ( existing_function )
+     {
+ 	// Just get rid of the placeholder
+ 	existing_function->dropAllReferences();
+ 	delete existing_function;
+     }
+ #endif
+ 
+     // Just set the name of the function now that we know what it is.
+     f->setName( name );
+ 
+     free( name );
+ 
+     return f;
+ }
+ 
+ Function*
+ StackerCompiler::handle_word_list_start()
+ {
+     TheFunction = new Function(DefinitionType, GlobalValue::ExternalLinkage);
+     return TheFunction;
+ }
+ 
+ Function*
+ StackerCompiler::handle_word_list_end( Function* f, BasicBlock* bb )
+ {
+     add_block( f, bb );
+     return f;
+ }
+ 
+ BasicBlock* 
+ StackerCompiler::handle_if( char* ifTrue, char* ifFalse )
+ {
+     // Create a basic block for the preamble
+     BasicBlock* bb = new BasicBlock((echo?"if":""));
+ 
+     // Get the condition value
+     LoadInst* cond = cast<LoadInst>( pop_integer(bb) );
+ 
+     // Compare the condition against 0 
+     SetCondInst* cond_inst = new SetCondInst( Instruction::SetNE, cond, 
+ 	ConstantSInt::get( Type::IntTy, 0) );
+     bb->getInstList().push_back( cond_inst );
+ 
+     // Create an exit block
+     BasicBlock* exit_bb = new BasicBlock((echo?"endif":""));
+ 
+     // Create the true_block
+     BasicBlock* true_bb = new BasicBlock((echo?"then":""));
+ 
+     // Create the false_block
+     BasicBlock* false_bb = 0;
+     if ( ifFalse ) false_bb = new BasicBlock((echo?"else":""));
+ 
+     // Create a branch on the SetCond
+     BranchInst* br_inst = new BranchInst( true_bb, 
+ 	( ifFalse ? false_bb : exit_bb ), cond_inst );
+     bb->getInstList().push_back( br_inst );
+ 
+     // Fill the true block 
+     std::vector<Value*> args;
+     if ( Function* true_func = TheModule->getNamedFunction(ifTrue) )
+     {
+ 	true_bb->getInstList().push_back( 
+ 		new CallInst( true_func, args ) );
+ 	true_bb->getInstList().push_back( 
+ 		new BranchInst( exit_bb ) );
+     }
+     else
+     {
+ 	ThrowException(std::string("Function '") + ifTrue + 
+ 	    "' must be declared first.'");
+     }
+ 
+     free( ifTrue );
+ 
+     // Fill the false block
+     if ( false_bb )
+     {
+ 	if ( Function* false_func = TheModule->getNamedFunction(ifFalse) )
+ 	{
+ 	    false_bb->getInstList().push_back( 
+ 		    new CallInst( false_func, args ) );
+ 	    false_bb->getInstList().push_back( 
+ 		    new BranchInst( exit_bb ) );
+ 	}
+ 	else
+ 	{
+ 	    ThrowException(std::string("Function '") + ifFalse + 
+ 		    "' must be declared first.'");
+ 	}
+ 	free( ifFalse );
+     }
+ 
+     // Add the blocks to the function
+     add_block( TheFunction, bb );
+     add_block( TheFunction, true_bb );
+     if ( false_bb ) add_block( TheFunction, false_bb );
+ 
+     return exit_bb;
+ }
+ 
+ BasicBlock* 
+ StackerCompiler::handle_while( char* todo )
+ {
+ 
+     // Create a basic block for the loop test
+     BasicBlock* test = new BasicBlock((echo?"while":""));
+ 
+     // Create an exit block
+     BasicBlock* exit = new BasicBlock((echo?"end":""));
+ 
+     // Create a loop body block
+     BasicBlock* body = new BasicBlock((echo?"do":""));
+ 
+     // Create a root node
+     BasicBlock* bb = new BasicBlock((echo?"root":""));
+     BranchInst* root_br_inst = new BranchInst( test );
+     bb->getInstList().push_back( root_br_inst );
+ 
+     // Pop the condition value
+     LoadInst* cond = cast<LoadInst>( stack_top(test) );
+ 
+     // Compare the condition against 0 
+     SetCondInst* cond_inst = new SetCondInst( 
+ 	Instruction::SetNE, cond, ConstantSInt::get( Type::IntTy, 0) );
+     test->getInstList().push_back( cond_inst );
+ 
+     // Add the branch instruction
+     BranchInst* br_inst = new BranchInst( body, exit, cond_inst );
+     test->getInstList().push_back( br_inst );
+ 
+     // Fill in the body
+     std::vector<Value*> args;
+     if ( Function* body_func = TheModule->getNamedFunction(todo) )
+     {
+ 	body->getInstList().push_back( new CallInst( body_func, args ) );
+ 	body->getInstList().push_back( new BranchInst( test ) );
+     }
+     else
+     {
+ 	ThrowException(std::string("Function '") + todo + 
+ 	    "' must be declared first.'");
+     }
+ 
+     free( todo );
+ 
+     // Add the blocks
+     add_block( TheFunction, bb );
+     add_block( TheFunction, test );
+     add_block( TheFunction, body );
+ 
+     return exit;
+ }
+ 
+ BasicBlock* 
+ StackerCompiler::handle_identifier( char * name )
+ {
+     Function* func = TheModule->getNamedFunction( name );
+     BasicBlock* bb = new BasicBlock((echo?"call":""));
+     if ( func )
+     {
+ 	CallInst* call_def = new CallInst( func , no_arguments );
+ 	bb->getInstList().push_back( call_def );
+     }
+     else
+     {
+ 	ThrowException(std::string("Definition '") + name + 
+ 	    "' must be defined before it can be used.");
+     }
+ 
+     free( name );
+     return bb;
+ }
+ 
+ BasicBlock* 
+ StackerCompiler::handle_string( char * value )
+ {
+     // Create a new basic block for the push operation
+     BasicBlock* bb = new BasicBlock((echo?"string":""));
+ 
+     // Push the string onto the stack
+     push_string(bb, value);
+ 
+     // Free the strdup'd string
+     free( value );
+ 
+     return bb;
+ }
+ 
+ BasicBlock* 
+ StackerCompiler::handle_integer( const int32_t value )
+ {
+     // Create a new basic block for the push operation
+     BasicBlock* bb = new BasicBlock((echo?"int":""));
+ 
+     // Push the integer onto the stack
+     push_integer(bb, value );
+ 
+     return bb;
+ }
+ 
+ BasicBlock* 
+ StackerCompiler::handle_word( int tkn )
+ {
+     // Create a new basic block to hold the instruction(s)
+     BasicBlock* bb = new BasicBlock();
+ 
+     /* Fill the basic block with the appropriate instructions */
+     switch ( tkn )
+     {
+     case DUMP :  // Dump the stack (debugging aid)
+     {
+ 	if (echo) bb->setName("DUMP");
+ 	Function* f = TheModule->getOrInsertFunction(
+ 	    "_stacker_dump_stack_", DefinitionType);
+ 	std::vector<Value*> args;
+ 	bb->getInstList().push_back( new CallInst( f, args ) );
+ 	break;
+     }
+ 
+     // Logical Operations
+     case TRUE :  // -- -1
+     {
+ 	if (echo) bb->setName("TRUE");
+ 	push_integer(bb,-1); 
+ 	break;
+     }
+     case FALSE : // -- 0
+     {
+ 	if (echo) bb->setName("FALSE");
+ 	push_integer(bb,0); 
+ 	break;
+     }
+     case LESS : // w1 w2 -- w2<w1
+     {
+ 	if (echo) bb->setName("LESS");
+ 	LoadInst* op1 = cast<LoadInst>(pop_integer(bb));
+ 	LoadInst* op2 = cast<LoadInst>(pop_integer(bb));
+ 	SetCondInst* cond_inst = 
+ 	    new SetCondInst( Instruction::SetLT, op1, op2 );
+ 	bb->getInstList().push_back( cond_inst );
+ 	push_value( bb, cond_inst );
+ 	break;
+     }
+     case MORE : // w1 w2 -- w2>w1
+     {
+ 	if (echo) bb->setName("MORE");
+ 	LoadInst* op1 = cast<LoadInst>(pop_integer(bb));
+ 	LoadInst* op2 = cast<LoadInst>(pop_integer(bb));
+ 	SetCondInst* cond_inst = 
+ 	    new SetCondInst( Instruction::SetGT, op1, op2 );
+ 	bb->getInstList().push_back( cond_inst );
+ 	push_value( bb, cond_inst );
+ 	break;
+     }
+     case LESS_EQUAL : // w1 w2 -- w2<=w1
+     {
+ 	if (echo) bb->setName("LE");
+ 	LoadInst* op1 = cast<LoadInst>(pop_integer(bb));
+ 	LoadInst* op2 = cast<LoadInst>(pop_integer(bb));
+ 	SetCondInst* cond_inst = 
+ 	    new SetCondInst( Instruction::SetLE, op1, op2 );
+ 	bb->getInstList().push_back( cond_inst );
+ 	push_value( bb, cond_inst );
+ 	break;
+     }
+     case MORE_EQUAL : // w1 w2 -- w2>=w1
+     {
+ 	if (echo) bb->setName("GE");
+ 	LoadInst* op1 = cast<LoadInst>(pop_integer(bb));
+ 	LoadInst* op2 = cast<LoadInst>(pop_integer(bb));
+ 	SetCondInst* cond_inst = 
+ 	    new SetCondInst( Instruction::SetGE, op1, op2 );
+ 	bb->getInstList().push_back( cond_inst );
+ 	push_value( bb, cond_inst );
+ 	break;
+     }
+     case NOT_EQUAL : // w1 w2 -- w2!=w1
+     {
+ 	if (echo) bb->setName("NE");
+ 	LoadInst* op1 = cast<LoadInst>(pop_integer(bb));
+ 	LoadInst* op2 = cast<LoadInst>(pop_integer(bb));
+ 	SetCondInst* cond_inst = 
+ 	    new SetCondInst( Instruction::SetNE, op1, op2 );
+ 	bb->getInstList().push_back( cond_inst );
+ 	push_value( bb, cond_inst );
+ 	break;
+     }
+     case EQUAL : // w1 w2 -- w1==w2
+     {
+ 	if (echo) bb->setName("EQ");
+ 	LoadInst* op1 = cast<LoadInst>(pop_integer(bb));
+ 	LoadInst* op2 = cast<LoadInst>(pop_integer(bb));
+ 	SetCondInst* cond_inst = 
+ 	    new SetCondInst( Instruction::SetEQ, op1, op2 );
+ 	bb->getInstList().push_back( cond_inst );
+ 	push_value( bb, cond_inst );
+ 	break;
+     }
+ 
+     // Arithmetic Operations
+     case PLUS : // w1 w2 -- w2+w1
+     {
+ 	if (echo) bb->setName("ADD");
+ 	LoadInst* op1 = cast<LoadInst>(pop_integer(bb));
+ 	LoadInst* op2 = cast<LoadInst>(pop_integer(bb));
+ 	BinaryOperator* addop = 
+ 	    BinaryOperator::create( Instruction::Add, op1, op2);
+ 	bb->getInstList().push_back( addop );
+ 	push_value( bb, addop );
+ 	break;
+     }
+     case MINUS : // w1 w2 -- w2-w1
+     {
+ 	if (echo) bb->setName("SUB");
+ 	LoadInst* op1 = cast<LoadInst>(pop_integer(bb));
+ 	LoadInst* op2 = cast<LoadInst>(pop_integer(bb));
+ 	BinaryOperator* subop = 
+ 	    BinaryOperator::create( Instruction::Sub, op1, op2);
+ 	bb->getInstList().push_back( subop );
+ 	push_value( bb, subop );
+ 	break;
+     }
+     case INCR :  // w1 -- w1+1
+     {
+ 	if (echo) bb->setName("INCR");
+ 	LoadInst* op1 = cast<LoadInst>(pop_integer(bb));
+ 	BinaryOperator* addop = 
+ 	    BinaryOperator::create( Instruction::Add, op1, IOne );
+ 	bb->getInstList().push_back( addop );
+ 	push_value( bb, addop );
+ 	break;
+     }
+     case DECR : // w1 -- w1-1
+     {
+ 	if (echo) bb->setName("DECR");
+ 	LoadInst* op1 = cast<LoadInst>(pop_integer(bb));
+ 	BinaryOperator* subop = BinaryOperator::create( Instruction::Sub, op1,
+ 	    ConstantSInt::get( Type::IntTy, 1 ) );
+ 	bb->getInstList().push_back( subop );
+ 	push_value( bb, subop );
+ 	break;
+     }
+     case MULT : // w1 w2 -- w2*w1
+     {
+ 	if (echo) bb->setName("MUL");
+ 	LoadInst* op1 = cast<LoadInst>(pop_integer(bb));
+ 	LoadInst* op2 = cast<LoadInst>(pop_integer(bb));
+ 	BinaryOperator* multop = 
+ 	    BinaryOperator::create( Instruction::Mul, op1, op2);
+ 	bb->getInstList().push_back( multop );
+ 	push_value( bb, multop );
+ 	break;
+     }
+     case DIV :// w1 w2 -- w2/w1
+     {
+ 	if (echo) bb->setName("DIV");
+ 	LoadInst* op1 = cast<LoadInst>(pop_integer(bb));
+ 	LoadInst* op2 = cast<LoadInst>(pop_integer(bb));
+ 	BinaryOperator* divop = 
+ 	    BinaryOperator::create( Instruction::Div, op1, op2);
+ 	bb->getInstList().push_back( divop );
+ 	push_value( bb, divop );
+ 	break;
+     }
+     case MODULUS : // w1 w2 -- w2%w1
+     {
+ 	if (echo) bb->setName("MOD");
+ 	LoadInst* op1 = cast<LoadInst>(pop_integer(bb));
+ 	LoadInst* op2 = cast<LoadInst>(pop_integer(bb));
+ 	BinaryOperator* divop = 
+ 	    BinaryOperator::create( Instruction::Rem, op1, op2);
+ 	bb->getInstList().push_back( divop );
+ 	push_value( bb, divop );
+ 	break;
+     }
+     case STAR_SLASH : // w1 w2 w3 -- (w3*w2)/w1
+     {
+ 	if (echo) bb->setName("STAR_SLASH");
+ 	// Get the operands
+ 	LoadInst* op1 = cast<LoadInst>(pop_integer(bb));
+ 	LoadInst* op2 = cast<LoadInst>(pop_integer(bb));
+ 	LoadInst* op3 = cast<LoadInst>(pop_integer(bb));
+ 
+ 	// Multiply the first two
+ 	BinaryOperator* multop = 
+ 	    BinaryOperator::create( Instruction::Mul, op1, op2);
+ 	bb->getInstList().push_back( multop );
+ 
+ 	// Divide by the third operand
+ 	BinaryOperator* divop = 
+ 	    BinaryOperator::create( Instruction::Div, multop, op3);
+ 	bb->getInstList().push_back( divop );
+ 
+ 	// Push the result
+ 	push_value( bb, divop );
+ 
+ 	break;
+     }
+     case NEGATE : // w1 -- -w1
+     {
+ 	if (echo) bb->setName("NEG");
+ 	LoadInst* op1 = cast<LoadInst>(pop_integer(bb));
+ 	// APPARENTLY, the following doesn't work:
+ 	// BinaryOperator* negop = BinaryOperator::createNeg( op1 );
+ 	// bb->getInstList().push_back( negop );
+ 	// So we'll multiply by -1 (ugh)
+ 	BinaryOperator* multop = BinaryOperator::create( Instruction::Mul, op1,
+ 	    ConstantSInt::get( Type::IntTy, -1 ) );
+ 	bb->getInstList().push_back( multop );
+ 	push_value( bb, multop );
+ 	break;
+     }
+     case ABS : // w1 -- |w1|
+     {
+ 	if (echo) bb->setName("ABS");
+ 	// Get the top of stack value
+ 	LoadInst* op1 = cast<LoadInst>(stack_top(bb));
+ 
+ 	// Determine if its negative
+ 	SetCondInst* cond_inst = 
+ 	    new SetCondInst( Instruction::SetLT, op1, IZero );
+ 	bb->getInstList().push_back( cond_inst );
+ 
+ 	// Create a block for storing the result
+ 	BasicBlock* exit_bb = new BasicBlock((echo?"exit":""));
+ 
+ 	// Create a block for making it a positive value
+ 	BasicBlock* pos_bb = new BasicBlock((echo?"neg":""));
+ 
+ 	// Create the branch on the SetCond
+ 	BranchInst* br_inst = new BranchInst( pos_bb, exit_bb, cond_inst );
+ 	bb->getInstList().push_back( br_inst );
+ 
+ 	// Fill out the negation block
+ 	LoadInst* pop_op = cast<LoadInst>( pop_integer(pos_bb) );
+ 	BinaryOperator* neg_op = BinaryOperator::createNeg( pop_op );
+ 	pos_bb->getInstList().push_back( neg_op );
+ 	push_value( pos_bb, neg_op );
+ 	pos_bb->getInstList().push_back( new BranchInst( exit_bb ) );
+ 
+ 	// Add the new blocks in the correct order
+ 	add_block( TheFunction, bb );
+ 	add_block( TheFunction, pos_bb );
+ 	bb = exit_bb;
+ 	break;
+     }
+     case MIN : // w1 w2 -- (w2<w1?w2:w1)
+     {
+ 	if (echo) bb->setName("MIN");
+ 
+ 	// Create the three blocks
+ 	BasicBlock* exit_bb  = new BasicBlock((echo?"exit":""));
+ 	BasicBlock* op1_block = new BasicBlock((echo?"less":""));
+ 	BasicBlock* op2_block = new BasicBlock((echo?"more":""));
+ 
+ 	// Get the two operands
+ 	LoadInst* op1 = cast<LoadInst>(pop_integer(bb));
+ 	LoadInst* op2 = cast<LoadInst>(pop_integer(bb));
+ 
+ 	// Compare them 
+ 	SetCondInst* cond_inst = 
+ 	    new SetCondInst( Instruction::SetLT, op1, op2);
+ 	bb->getInstList().push_back( cond_inst );
+ 
+ 	// Create a branch on the SetCond
+ 	BranchInst* br_inst = 
+ 	    new BranchInst( op1_block, op2_block, cond_inst );
+ 	bb->getInstList().push_back( br_inst );
+ 
+ 	// Create a block for pushing the first one
+ 	push_value(op1_block, op1);
+ 	op1_block->getInstList().push_back( new BranchInst( exit_bb ) );
+ 
+ 	// Create a block for pushing the second one
+ 	push_value(op2_block, op2);
+ 	op2_block->getInstList().push_back( new BranchInst( exit_bb ) );
+ 
+ 	// Add the blocks
+ 	add_block( TheFunction, bb );
+ 	add_block( TheFunction, op1_block );
+ 	add_block( TheFunction, op2_block );
+ 	bb = exit_bb;
+ 	break;
+     }
+     case MAX : // w1 w2 -- (w2>w1?w2:w1)
+     {
+ 	if (echo) bb->setName("MAX");
+ 	// Get the two operands
+ 	LoadInst* op1 = cast<LoadInst>(pop_integer(bb));
+ 	LoadInst* op2 = cast<LoadInst>(pop_integer(bb));
+ 
+ 	// Compare them 
+ 	SetCondInst* cond_inst = 
+ 	    new SetCondInst( Instruction::SetGT, op1, op2);
+ 	bb->getInstList().push_back( cond_inst );
+ 
+ 	// Create an exit block
+ 	BasicBlock* exit_bb = new BasicBlock((echo?"exit":""));
+ 
+ 	// Create a block for pushing the larger one
+ 	BasicBlock* op1_block = new BasicBlock((echo?"more":""));
+ 	push_value(op1_block, op1);
+ 	op1_block->getInstList().push_back( new BranchInst( exit_bb ) );
+ 
+ 	// Create a block for pushing the smaller or equal one
+ 	BasicBlock* op2_block = new BasicBlock((echo?"less":""));
+ 	push_value(op2_block, op2);
+ 	op2_block->getInstList().push_back( new BranchInst( exit_bb ) );
+ 
+ 	// Create a banch on the SetCond
+ 	BranchInst* br_inst = 
+ 	    new BranchInst( op1_block, op2_block, cond_inst );
+ 	bb->getInstList().push_back( br_inst );
+ 
+ 	// Add the blocks
+ 	add_block( TheFunction, bb );
+ 	add_block( TheFunction, op1_block );
+ 	add_block( TheFunction, op2_block );
+ 
+ 	bb = exit_bb;
+ 	break;
+     }
+ 
+     // Bitwise Operators
+     case AND : // w1 w2 -- w2&w1
+     {
+ 	if (echo) bb->setName("AND");
+ 	LoadInst* op1 = cast<LoadInst>(pop_integer(bb));
+ 	LoadInst* op2 = cast<LoadInst>(pop_integer(bb));
+ 	BinaryOperator* andop = 
+ 	    BinaryOperator::create( Instruction::And, op1, op2);
+ 	bb->getInstList().push_back( andop );
+ 	push_value( bb, andop );
+ 	break;
+     }
+     case OR : // w1 w2 -- w2|w1
+     {
+ 	if (echo) bb->setName("OR");
+ 	LoadInst* op1 = cast<LoadInst>(pop_integer(bb));
+ 	LoadInst* op2 = cast<LoadInst>(pop_integer(bb));
+ 	BinaryOperator* orop = 
+ 	    BinaryOperator::create( Instruction::Or, op1, op2);
+ 	bb->getInstList().push_back( orop );
+ 	push_value( bb, orop );
+ 	break;
+     }
+     case XOR : // w1 w2 -- w2^w1
+     {
+ 	if (echo) bb->setName("XOR");
+ 	LoadInst* op1 = cast<LoadInst>(pop_integer(bb));
+ 	LoadInst* op2 = cast<LoadInst>(pop_integer(bb));
+ 	BinaryOperator* xorop = 
+ 	    BinaryOperator::create( Instruction::Xor, op1, op2);
+ 	bb->getInstList().push_back( xorop );
+ 	push_value( bb, xorop );
+ 	break;
+     }
+     case LSHIFT : // w1 w2 -- w1<<w2
+     {
+ 	if (echo) bb->setName("SHL");
+ 	LoadInst* op1 = cast<LoadInst>(pop_integer(bb));
+ 	LoadInst* op2 = cast<LoadInst>(pop_integer(bb));
+ 	CastInst* castop = new CastInst( op1, Type::UByteTy );
+ 	bb->getInstList().push_back( castop );
+ 	ShiftInst* shlop = new ShiftInst( Instruction::Shl, op2, castop );
+ 	bb->getInstList().push_back( shlop );
+ 	push_value( bb, shlop );
+ 	break;
+     }
+     case RSHIFT :  // w1 w2 -- w1>>w2
+     {
+ 	if (echo) bb->setName("SHR");
+ 	LoadInst* op1 = cast<LoadInst>(pop_integer(bb));
+ 	LoadInst* op2 = cast<LoadInst>(pop_integer(bb));
+ 	CastInst* castop = new CastInst( op1, Type::UByteTy );
+ 	bb->getInstList().push_back( castop );
+ 	ShiftInst* shrop = new ShiftInst( Instruction::Shr, op2, castop );
+ 	bb->getInstList().push_back( shrop );
+ 	push_value( bb, shrop );
+ 	break;
+     }
+ 
+     // Stack Manipulation Operations
+     case DROP:   	// w -- 
+     {
+ 	if (echo) bb->setName("DROP");
+ 	decr_stack_index(bb, One);
+ 	break;
+     }
+     case DROP2:	// w1 w2 -- 
+     {
+ 	if (echo) bb->setName("DROP2");
+ 	decr_stack_index( bb, Two );
+ 	break;
+     }
+     case NIP:	// w1 w2 -- w2
+     {
+ 	if (echo) bb->setName("NIP");
+ 	LoadInst* w2 = cast<LoadInst>( stack_top( bb ) );
+ 	decr_stack_index( bb  );
+ 	replace_top( bb, w2 );
+ 	break;
+     }
+     case NIP2:	// w1 w2 w3 w4 -- w3 w4
+     {
+ 	if (echo) bb->setName("NIP2");
+ 	LoadInst* w4 = cast<LoadInst>( stack_top( bb ) );
+ 	LoadInst* w3 = cast<LoadInst>( stack_top( bb, One ) );
+ 	decr_stack_index( bb, Two );
+ 	replace_top( bb, w4 );
+ 	replace_top( bb, w3, One );
+ 	break;
+     }
+     case DUP:	// w -- w w
+     {
+ 	if (echo) bb->setName("DUP");
+ 	LoadInst* w = cast<LoadInst>( stack_top( bb ) );
+ 	push_value( bb, w );
+ 	break;
+     }
+     case DUP2:	// w1 w2 -- w1 w2 w1 w2
+     {
+ 	if (echo) bb->setName("DUP2");
+ 	LoadInst* w2 = cast<LoadInst>( stack_top(bb) );
+ 	LoadInst* w1 = cast<LoadInst>( stack_top(bb, One ) );
+ 	incr_stack_index( bb, Two );
+ 	replace_top( bb, w1, One );
+ 	replace_top( bb, w2 );
+ 	break;
+     }
+     case SWAP:	// w1 w2 -- w2 w1
+     {
+ 	if (echo) bb->setName("SWAP");
+ 	LoadInst* w2 = cast<LoadInst>( stack_top( bb ) );
+ 	LoadInst* w1 = cast<LoadInst>( stack_top( bb, One ) );
+ 	replace_top( bb, w1 );
+ 	replace_top( bb, w2, One );
+ 	break;
+     }
+     case SWAP2:	// w1 w2 w3 w4 -- w3 w4 w1 w2
+     {
+ 	if (echo) bb->setName("SWAP2");
+ 	LoadInst* w4 = cast<LoadInst>( stack_top( bb ) );
+ 	LoadInst* w3 = cast<LoadInst>( stack_top( bb, One ) );
+ 	LoadInst* w2 = cast<LoadInst>( stack_top( bb, Two ) );
+ 	LoadInst* w1 = cast<LoadInst>( stack_top( bb, Three ) );
+ 	replace_top( bb, w2 );
+ 	replace_top( bb, w1, One );
+ 	replace_top( bb, w4, Two );
+ 	replace_top( bb, w3, Three );
+ 	break;
+     }
+     case OVER:	// w1 w2 -- w1 w2 w1
+     {
+ 	if (echo) bb->setName("OVER");
+ 	LoadInst* w1 = cast<LoadInst>( stack_top( bb, One ) );
+ 	push_value( bb, w1 );
+ 	break;
+     }
+     case OVER2:	// w1 w2 w3 w4 -- w1 w2 w3 w4 w1 w2
+     {
+ 	if (echo) bb->setName("OVER2");
+ 	LoadInst* w2 = cast<LoadInst>( stack_top( bb, Two ) );
+ 	LoadInst* w1 = cast<LoadInst>( stack_top( bb, Three ) );
+ 	incr_stack_index( bb, Two );
+ 	replace_top( bb, w2 );
+ 	replace_top( bb, w1, One );
+ 	break;
+     }
+     case ROT:	// w1 w2 w3 -- w2 w3 w1
+     {
+ 	if (echo) bb->setName("ROT");
+ 	LoadInst* w3 = cast<LoadInst>( stack_top( bb ) );
+ 	LoadInst* w2 = cast<LoadInst>( stack_top( bb, One ) );
+ 	LoadInst* w1 = cast<LoadInst>( stack_top( bb, Two ) );
+ 	replace_top( bb, w1 );
+ 	replace_top( bb, w3, One );
+ 	replace_top( bb, w2, Two );
+ 	break;
+     }
+     case ROT2:	// w1 w2 w3 w4 w5 w6 -- w3 w4 w5 w6 w1 w2
+     {
+ 	if (echo) bb->setName("ROT2");
+ 	LoadInst* w6 = cast<LoadInst>( stack_top( bb ) );
+ 	LoadInst* w5 = cast<LoadInst>( stack_top( bb, One ) );
+ 	LoadInst* w4 = cast<LoadInst>( stack_top( bb, Two ) );
+ 	LoadInst* w3 = cast<LoadInst>( stack_top( bb, Three) );
+ 	LoadInst* w2 = cast<LoadInst>( stack_top( bb, Four ) );
+ 	LoadInst* w1 = cast<LoadInst>( stack_top( bb, Five ) );
+ 	replace_top( bb, w2 );
+ 	replace_top( bb, w1, One );
+ 	replace_top( bb, w6, Two );
+ 	replace_top( bb, w5, Three );
+ 	replace_top( bb, w4, Four );
+ 	replace_top( bb, w3, Five );
+ 	break;
+     }
+     case RROT:	// w1 w2 w3 -- w3 w1 w2
+     {
+ 	if (echo) bb->setName("RROT2");
+ 	LoadInst* w3 = cast<LoadInst>( stack_top( bb ) );
+ 	LoadInst* w2 = cast<LoadInst>( stack_top( bb, One ) );
+ 	LoadInst* w1 = cast<LoadInst>( stack_top( bb, Two ) );
+ 	replace_top( bb, w2 );
+ 	replace_top( bb, w1, One );
+ 	replace_top( bb, w3, Two );
+ 	break;
+     }
+     case RROT2:	// w1 w2 w3 w4 w5 w6 -- w5 w6 w1 w2 w3 w4
+     {
+ 	if (echo) bb->setName("RROT2");
+ 	LoadInst* w6 = cast<LoadInst>( stack_top( bb ) );
+ 	LoadInst* w5 = cast<LoadInst>( stack_top( bb, One ) );
+ 	LoadInst* w4 = cast<LoadInst>( stack_top( bb, Two ) );
+ 	LoadInst* w3 = cast<LoadInst>( stack_top( bb, Three) );
+ 	LoadInst* w2 = cast<LoadInst>( stack_top( bb, Four ) );
+ 	LoadInst* w1 = cast<LoadInst>( stack_top( bb, Five ) );
+ 	replace_top( bb, w4 );
+ 	replace_top( bb, w3, One );
+ 	replace_top( bb, w2, Two );
+ 	replace_top( bb, w1, Three );
+ 	replace_top( bb, w6, Four );
+ 	replace_top( bb, w5, Five );
+ 	break;
+     }
+     case TUCK:	// w1 w2 -- w2 w1 w2
+     {
+ 	if (echo) bb->setName("TUCK");
+ 	LoadInst* w2 = cast<LoadInst>( stack_top( bb ) );
+ 	LoadInst* w1 = cast<LoadInst>( stack_top( bb, One ) );
+ 	incr_stack_index( bb );
+ 	replace_top( bb, w2 );
+ 	replace_top( bb, w1, One );
+ 	replace_top( bb, w2, Two );
+ 	break;
+     }
+     case TUCK2:	// w1 w2 w3 w4 -- w3 w4 w1 w2 w3 w4 
+     {
+ 	if (echo) bb->setName("TUCK2");
+ 	LoadInst* w4 = cast<LoadInst>( stack_top( bb ) );
+ 	LoadInst* w3 = cast<LoadInst>( stack_top( bb, One ) );
+ 	LoadInst* w2 = cast<LoadInst>( stack_top( bb, Two ) );
+ 	LoadInst* w1 = cast<LoadInst>( stack_top( bb, Three) );
+ 	incr_stack_index( bb, Two );
+ 	replace_top( bb, w4 );
+ 	replace_top( bb, w3, One );
+ 	replace_top( bb, w2, Two );
+ 	replace_top( bb, w1, Three );
+ 	replace_top( bb, w4, Four );
+ 	replace_top( bb, w3, Five );
+ 	break;
+     }
+     case ROLL:	// x0 x1 .. xn n -- x1 .. xn x0
+     {
+ 	/// THIS OEPRATOR IS OMITTED PURPOSEFULLY AND IS LEFT TO THE 
+ 	/// READER AS AN EXERCISE. THIS IS ONE OF THE MORE COMPLICATED
+ 	/// OPERATORS. IF YOU CAN GET THIS ONE RIGHT, YOU COMPLETELY
+ 	/// UNDERSTAND HOW BOTH LLVM AND STACKER WOR.  
+ 	/// HINT: LOOK AT PICK AND SELECT. ROLL IS SIMILAR.
+ 	if (echo) bb->setName("ROLL");
+ 	break;
+     }
+     case PICK:	// x0 ... Xn n -- x0 ... Xn x0
+     {
+ 	if (echo) bb->setName("PICK");
+ 	LoadInst* n = cast<LoadInst>( stack_top( bb ) );
+ 	BinaryOperator* addop = 
+ 	    BinaryOperator::create( Instruction::Add, n, IOne );
+ 	bb->getInstList().push_back( addop );
+ 	LoadInst* x0 = cast<LoadInst>( stack_top( bb, addop ) );
+ 	replace_top( bb, x0 );
+ 	break;
+     }
+     case SELECT:	// m n X0..Xm Xm+1 .. Xn -- Xm
+     {
+ 	if (echo) bb->setName("SELECT");
+ 	LoadInst* m = cast<LoadInst>( stack_top(bb) );
+ 	LoadInst* n = cast<LoadInst>( stack_top(bb, One) );
+ 	BinaryOperator* index = 
+ 	    BinaryOperator::create( Instruction::Add, m, IOne );
+ 	bb->getInstList().push_back( index );
+ 	LoadInst* Xm = cast<LoadInst>( stack_top(bb, index ) );
+ 	BinaryOperator* n_plus_1 = 
+ 	    BinaryOperator::create( Instruction::Add, n, IOne );
+ 	bb->getInstList().push_back( n_plus_1 );
+ 	decr_stack_index( bb, n_plus_1 );
+ 	replace_top( bb, Xm );
+ 	break;
+     }
+     case MALLOC : // n -- p
+     {
+ 	if (echo) bb->setName("MALLOC");
+ 	// Get the number of bytes to mallocate
+ 	LoadInst* op1 = cast<LoadInst>( pop_integer(bb) );
+ 
+ 	// Make sure its a UIntTy
+ 	CastInst* caster = new CastInst( op1, Type::UIntTy );
+ 	bb->getInstList().push_back( caster );
+ 
+ 	// Allocate the bytes
+ 	MallocInst* mi = new MallocInst( Type::SByteTy, caster );
+ 	bb->getInstList().push_back( mi );
+ 
+ 	// Push the pointer
+ 	push_value( bb, mi );
+ 	break;
+     }
+     case FREE :  // p --
+     {
+ 	if (echo) bb->setName("FREE");
+ 	// Pop the value off the stack
+ 	CastInst* ptr = cast<CastInst>( pop_string(bb) );
+ 
+ 	// Free the memory
+ 	FreeInst* fi = new FreeInst( ptr );
+ 	bb->getInstList().push_back( fi );
+ 
+ 	break;
+     }
+     case GET : // p w1 -- p w2
+     {
+ 	if (echo) bb->setName("GET");
+ 	// Get the character index
+ 	LoadInst* op1 = cast<LoadInst>( stack_top(bb) );
+ 	CastInst* chr_idx = new CastInst( op1, Type::LongTy );
+ 	bb->getInstList().push_back( chr_idx );
+ 
+ 	// Get the String pointer
+ 	CastInst* ptr = cast<CastInst>( stack_top_string(bb,One) );
+ 
+ 	// Get address of op1'th element of the string
+ 	std::vector<Value*> indexVec;
+ 	indexVec.push_back( chr_idx );
+ 	GetElementPtrInst* gep = new GetElementPtrInst( ptr, indexVec );
+ 	bb->getInstList().push_back( gep );
+ 
+ 	// Get the value and push it
+ 	LoadInst* loader = new LoadInst( gep );
+ 	bb->getInstList().push_back( loader );
+ 	CastInst* caster = new CastInst( loader, Type::IntTy );
+ 	bb->getInstList().push_back( caster );
+ 
+ 	// Push the result back on stack
+ 	replace_top( bb, caster );
+ 
+ 	break;
+     }
+     case PUT : // p w2 w1  -- p
+     {
+ 	if (echo) bb->setName("PUT");
+ 
+ 	// Get the value to put
+ 	LoadInst* w1 = cast<LoadInst>( pop_integer(bb) );
+ 
+ 	// Get the character index
+ 	LoadInst* w2 = cast<LoadInst>( pop_integer(bb) );
+ 	CastInst* chr_idx = new CastInst( w2, Type::LongTy );
+ 	bb->getInstList().push_back( chr_idx );
+ 
+ 	// Get the String pointer
+ 	CastInst* ptr = cast<CastInst>( stack_top_string(bb) );
+ 
+ 	// Get address of op2'th element of the string
+ 	std::vector<Value*> indexVec;
+ 	indexVec.push_back( chr_idx );
+ 	GetElementPtrInst* gep = new GetElementPtrInst( ptr, indexVec );
+ 	bb->getInstList().push_back( gep );
+ 
+ 	// Cast the value and put it
+ 	CastInst* caster = new CastInst( w1, Type::SByteTy );
+ 	bb->getInstList().push_back( caster );
+ 	StoreInst* storer = new StoreInst( caster, gep );
+ 	bb->getInstList().push_back( storer );
+ 
+ 	break;
+     }
+     case RECURSE : 
+     {
+ 	if (echo) bb->setName("RECURSE");
+ 	std::vector<Value*> params;
+ 	CallInst* call_inst = new CallInst( TheFunction, params );
+ 	bb->getInstList().push_back( call_inst );
+ 	break;
+     }
+     case RETURN : 
+     {
+ 	if (echo) bb->setName("RETURN");
+ 	bb->getInstList().push_back( new ReturnInst() );
+ 	break;
+     }
+     case EXIT : 
+     {
+ 	if (echo) bb->setName("EXIT");
+ 	// Get the result value
+ 	LoadInst* op1 = cast<LoadInst>(pop_integer(bb));
+ 
+ 	// Call exit(3)
+ 	std::vector<Value*> params;
+ 	params.push_back(op1);
+ 	CallInst* call_inst = new CallInst( TheExit, params );
+ 	bb->getInstList().push_back( call_inst );
+ 	break;
+     }
+     case TAB :
+     {
+ 	if (echo) bb->setName("TAB");
+ 	// Get the format string for a character
+ 	std::vector<Value*> indexVec;
+ 	indexVec.push_back( Zero );
+ 	indexVec.push_back( Zero );
+ 	GetElementPtrInst* format_gep = 
+ 	    new GetElementPtrInst( ChrFormat, indexVec );
+ 	bb->getInstList().push_back( format_gep );
+ 
+ 	// Get the character to print (a newline)
+ 	ConstantSInt* newline = ConstantSInt::get(Type::IntTy, 
+ 	    static_cast<int>('\t'));
+ 
+ 	// Call printf
+ 	std::vector<Value*> args;
+ 	args.push_back( format_gep );
+ 	args.push_back( newline );
+ 	bb->getInstList().push_back( new CallInst( ThePrintf, args ) );
+ 	break;
+     }
+     case SPACE : 
+     {
+ 	if (echo) bb->setName("SPACE");
+ 	// Get the format string for a character
+ 	std::vector<Value*> indexVec;
+ 	indexVec.push_back( Zero );
+ 	indexVec.push_back( Zero );
+ 	GetElementPtrInst* format_gep = 
+ 	    new GetElementPtrInst( ChrFormat, indexVec );
+ 	bb->getInstList().push_back( format_gep );
+ 
+ 	// Get the character to print (a newline)
+ 	ConstantSInt* newline = ConstantSInt::get(Type::IntTy, 
+ 	    static_cast<int>(' '));
+ 
+ 	// Call printf
+ 	std::vector<Value*> args;
+ 	args.push_back( format_gep );
+ 	args.push_back( newline );
+ 	bb->getInstList().push_back( new CallInst( ThePrintf, args ) );
+ 	break;
+     }
+     case CR : 
+     {
+ 	if (echo) bb->setName("CR");
+ 	// Get the format string for a character
+ 	std::vector<Value*> indexVec;
+ 	indexVec.push_back( Zero );
+ 	indexVec.push_back( Zero );
+ 	GetElementPtrInst* format_gep = 
+ 	    new GetElementPtrInst( ChrFormat, indexVec );
+ 	bb->getInstList().push_back( format_gep );
+ 
+ 	// Get the character to print (a newline)
+ 	ConstantSInt* newline = ConstantSInt::get(Type::IntTy, 
+ 	    static_cast<int>('\n'));
+ 
+ 	// Call printf
+ 	std::vector<Value*> args;
+ 	args.push_back( format_gep );
+ 	args.push_back( newline );
+ 	bb->getInstList().push_back( new CallInst( ThePrintf, args ) );
+ 	break;
+     }
+     case IN_STR : 
+     {
+ 	if (echo) bb->setName("IN_STR");
+ 	// Make room for the value result
+ 	incr_stack_index(bb);
+ 	GetElementPtrInst* gep_value = 
+ 	    cast<GetElementPtrInst>(get_stack_pointer(bb));
+ 	CastInst* caster = 
+ 	    new CastInst( gep_value, PointerType::get( Type::SByteTy ) );
+ 
+ 	// Make room for the count result
+ 	incr_stack_index(bb);
+ 	GetElementPtrInst* gep_count = 
+ 	    cast<GetElementPtrInst>(get_stack_pointer(bb));
+ 
+ 	// Call scanf(3)
+ 	std::vector<Value*> args;
+ 	args.push_back( InStrFormat );
+ 	args.push_back( caster );
+ 	CallInst* scanf = new CallInst( TheScanf, args );
+ 	bb->getInstList().push_back( scanf );
+ 
+ 	// Store the result
+ 	bb->getInstList().push_back( new StoreInst( scanf, gep_count ) );
+ 	break;
+     }
+     case IN_NUM : 
+     {
+ 	if (echo) bb->setName("IN_NUM");
+ 	// Make room for the value result
+ 	incr_stack_index(bb);
+ 	GetElementPtrInst* gep_value = 
+ 	    cast<GetElementPtrInst>(get_stack_pointer(bb));
+ 
+ 	// Make room for the count result
+ 	incr_stack_index(bb);
+ 	GetElementPtrInst* gep_count = 
+ 	    cast<GetElementPtrInst>(get_stack_pointer(bb));
+ 
+ 	// Call scanf(3)
+ 	std::vector<Value*> args;
+ 	args.push_back( InStrFormat );
+ 	args.push_back( gep_value );
+ 	CallInst* scanf = new CallInst( TheScanf, args );
+ 	bb->getInstList().push_back( scanf );
+ 
+ 	// Store the result
+ 	bb->getInstList().push_back( new StoreInst( scanf, gep_count ) );
+ 	break;
+     }
+     case IN_CHAR :
+     {
+ 	if (echo) bb->setName("IN_CHAR");
+ 	// Make room for the value result
+ 	incr_stack_index(bb);
+ 	GetElementPtrInst* gep_value = 
+ 	    cast<GetElementPtrInst>(get_stack_pointer(bb));
+ 
+ 	// Make room for the count result
+ 	incr_stack_index(bb);
+ 	GetElementPtrInst* gep_count = 
+ 	    cast<GetElementPtrInst>(get_stack_pointer(bb));
+ 
+ 	// Call scanf(3)
+ 	std::vector<Value*> args;
+ 	args.push_back( InChrFormat );
+ 	args.push_back( gep_value );
+ 	CallInst* scanf = new CallInst( TheScanf, args );
+ 	bb->getInstList().push_back( scanf );
+ 
+ 	// Store the result
+ 	bb->getInstList().push_back( new StoreInst( scanf, gep_count ) );
+ 	break;
+     }
+     case OUT_STR : 
+     {
+ 	if (echo) bb->setName("OUT_STR");
+ 	LoadInst* op1 = cast<LoadInst>(stack_top(bb));
+ 
+ 	// Get the address of the format string
+ 	std::vector<Value*> indexVec;
+ 	indexVec.push_back( Zero );
+ 	indexVec.push_back( Zero );
+ 	GetElementPtrInst* format_gep = 
+ 	    new GetElementPtrInst( StrFormat, indexVec );
+ 	bb->getInstList().push_back( format_gep );
+ 	// Build function call arguments
+ 	std::vector<Value*> args;
+ 	args.push_back( format_gep );
+ 	args.push_back( op1 );
+ 	// Call printf
+ 	bb->getInstList().push_back( new CallInst( ThePrintf, args ) );
+ 	break;
+     }
+     case OUT_NUM : 
+     {
+ 	if (echo) bb->setName("OUT_NUM");
+ 	// Pop the numeric operand off the stack
+ 	LoadInst* op1 = cast<LoadInst>(stack_top(bb));
+ 
+ 	// Get the address of the format string
+ 	std::vector<Value*> indexVec;
+ 	indexVec.push_back( Zero );
+ 	indexVec.push_back( Zero );
+ 	GetElementPtrInst* format_gep = 
+ 	    new GetElementPtrInst( NumFormat, indexVec );
+ 	bb->getInstList().push_back( format_gep );
+ 
+ 	// Build function call arguments
+ 	std::vector<Value*> args;
+ 	args.push_back( format_gep );
+ 	args.push_back( op1 );
+ 
+ 	// Call printf
+ 	bb->getInstList().push_back( new CallInst( ThePrintf, args ) );
+ 	break;
+     }
+     case OUT_CHAR :
+     {
+ 	if (echo) bb->setName("OUT_CHAR");
+ 	// Pop the character operand off the stack
+ 	LoadInst* op1 = cast<LoadInst>(stack_top(bb));
+ 
+ 	// Get the address of the format string
+ 	std::vector<Value*> indexVec;
+ 	indexVec.push_back( Zero );
+ 	indexVec.push_back( Zero );
+ 	GetElementPtrInst* format_gep = 
+ 	    new GetElementPtrInst( ChrFormat, indexVec );
+ 	bb->getInstList().push_back( format_gep );
+ 
+ 	// Build function call arguments
+ 	std::vector<Value*> args;
+ 	args.push_back( format_gep );
+ 	args.push_back( op1 );
+ 	// Call printf
+ 	bb->getInstList().push_back( new CallInst( ThePrintf, args ) );
+ 	break;
+     }
+     default :
+     {
+ 	ThrowException(std::string("Compiler Error: Unhandled token #"));
+     }
+     }
+ 
+     // Return the basic block
+     return bb;
+ }


Index: llvm/projects/Stacker/lib/compiler/StackerCompiler.h
diff -c /dev/null llvm/projects/Stacker/lib/compiler/StackerCompiler.h:1.1
*** /dev/null	Sun Nov 23 11:53:05 2003
--- llvm/projects/Stacker/lib/compiler/StackerCompiler.h	Sun Nov 23 11:52:55 2003
***************
*** 0 ****
--- 1,224 ----
+ //===-- StackerCompiler.h - Interface to the Stacker Compiler ---*- C++ -*-===//
+ // 
+ //                     The LLVM Compiler Infrastructure
+ //
+ // This file was developed by Reid Spencer and donated to the LLVM research 
+ // group and is distributed under the University of Illinois Open Source 
+ // License. See LICENSE.TXT for details.
+ // 
+ //===----------------------------------------------------------------------===//
+ //
+ //  This header file defines the various variables that are shared among the 
+ //  different components of the parser...
+ //
+ //===----------------------------------------------------------------------===//
+ 
+ #ifndef LLVM_STACKERCOMPILER_H
+ #define LLVM_STACKERCOMPILER_H
+ 
+ #include <llvm/Constants.h>
+ #include <llvm/DerivedTypes.h>
+ #include <llvm/Function.h>
+ #include <llvm/Instruction.h>
+ #include <llvm/Module.h>
+ #include <llvm/Assembly/Parser.h>
+ #include <Support/StringExtras.h>
+ 
+ using namespace llvm;
+ 
+ // Global variables exported from the lexer...
+ extern std::FILE *Stackerin;
+ extern int Stackerlineno;
+ extern char* Stackertext;
+ extern int Stackerleng;
+ 
+ /// @brief This class provides the Compiler for the Stacker language. 
+ /// 
+ /// The main method to call is \c compile. The other methods are
+ /// all internal to the compiler and protected. In general the 
+ /// handle_* methods are called by the BISON generated parser
+ /// (see StackerParser.y). The methods returning Instruction* all
+ /// produce some snippet of code to manipulate the stack in some
+ /// way. These functions are just conveniences as they are used
+ /// often by the compiler.
+ class StackerCompiler
+ {
+     /// @name Constructors and Operators
+     /// @{
+     public:
+ 	/// Default Constructor
+ 	StackerCompiler();
+ 
+ 	/// Destructor
+ 	~StackerCompiler();
+     private:
+ 	/// Do not copy StackerCompilers
+ 	StackerCompiler(const StackerCompiler&);
+ 
+ 	/// Do not copy StackerCompilers.
+ 	StackerCompiler& operator=(const StackerCompiler& );
+ 
+     /// @}
+     /// @name High Level Interface
+     /// @{
+     public:
+ 	/// @brief Compile a single file to LLVM bytecode.
+ 	///
+ 	/// To use the StackerCompiler, just create one on
+ 	/// the stack and call this method.
+ 	Module* compile( 
+ 	    const std::string& filename, ///< File to compile
+ 	    bool echo, ///< Causes compiler to echo output
+ 	    size_t stack_size ); ///< Size of generated stack
+     /// @}
+     /// @name Accessors
+     /// @{
+     public:
+ 	/// @brief Returns the name of the file being compiled.
+ 	std::string& filename() { return CurFilename; }
+ 
+     /// @}
+     /// @name Parse Handling Methods
+     /// @{
+     private:
+ 	/// Allow only the parser to access these methods. No
+ 	/// one else should call them.
+ 	friend int Stackerparse();
+ 
+ 	/// @brief Handle the start of a module
+ 	Module* handle_module_start();
+ 
+ 	/// @brief Handle the end of a module
+ 	/// @param mod The module we're defining.
+ 	Module* handle_module_end( Module* mod );
+ 
+ 	/// @brief Handle the start of a list of definitions
+ 	Module* handle_definition_list_start( );
+ 
+ 	/// @brief Handle the end of a list of definitions
+ 	/// @param mod The module we're constructing
+ 	/// @param definition A definition (function) to add to the module
+ 	Module* handle_definition_list_end( Module* mod, Function* definition );
+ 
+ 	/// @brief Handle creation of the MAIN definition
+ 	/// @param func The function to be used as the MAIN definition
+ 	Function* handle_main_definition( Function* func );
+ 
+ 	/// @brief Handle a forward definition
+ 	/// @param name The name of the definition being declared
+ 	Function* handle_forward( char* name );
+ 
+ 	/// @brief Handle a general definition
+ 	/// @param name The name of the definition being defined
+ 	/// @param func The Function definition.
+ 	Function* handle_definition( char* name, Function* func );
+ 
+ 	/// @brief Handle the start of a definition's word list
+ 	Function* handle_word_list_start();
+ 
+ 	/// @brief Handle the end of a definition's word list
+ 	/// @param func The function to which the basic block is added
+ 	/// @param next The block to add to the function
+ 	Function* handle_word_list_end( Function* func, BasicBlock* next );
+ 
+ 	/// @brief Handle an if statement, possibly without an else
+ 	/// @brief ifTrue The block to execute if true
+ 	/// @brief ifFalse The optional block to execute if false
+ 	BasicBlock* handle_if( char* ifTrue, char* ifFalse = 0 );
+ 
+ 	/// @brief Handle a while statement
+ 	/// @brief todo The block to repeatedly execute
+ 	BasicBlock* handle_while( char* todo );
+ 
+ 	/// @brief Handle an identifier to call the identified definition
+ 	/// @param name The name of the identifier to be called.
+ 	BasicBlock* handle_identifier( char * name );
+ 
+ 	/// @brief Handle the push of a string onto the stack
+ 	/// @param value The string to be pushed.
+ 	BasicBlock* handle_string( char * value );
+ 
+ 	/// @brief Handle the push of an integer onto the stack.
+ 	/// @param value The integer value to be pushed.
+ 	BasicBlock* handle_integer( const int32_t value );
+ 
+ 	/// @brief Handle one of the reserved words (given as a token)
+ 	BasicBlock* handle_word( int tkn );
+ 
+     /// @}
+     /// @name Utility functions
+     /// @{
+     public:
+         /// @brief Throws an exception to indicate an error
+         /// @param message The message to be output
+ 	/// @param line Override for the current line no
+ 	static inline void ThrowException( const std::string &message, 
+ 		int line = -1) 	    
+ 	{
+ 	  if (line == -1) line = Stackerlineno;
+ 	  // TODO: column number in exception
+ 	  throw ParseException(TheInstance->CurFilename, message, line);
+ 	}
+     private:
+ 	/// @brief Generate code to increment the stack index
+ 	Instruction* incr_stack_index( BasicBlock* bb, Value* );
+ 	/// @brief Generate code to decrement the stack index.
+ 	Instruction* decr_stack_index( BasicBlock* bb, Value* );
+ 	/// @brief Generate code to dereference the top of stack.
+ 	Instruction* get_stack_pointer( BasicBlock* bb, Value* );
+ 	/// @brief Generate code to push any value onto the stack.
+ 	Instruction* push_value( BasicBlock* bb, Value* value );
+ 	/// @brief Generate code to push a constant integer onto the stack.
+ 	Instruction* push_integer( BasicBlock* bb, int32_t value );
+ 	/// @brief Generate code to pop an integer off the stack.
+ 	Instruction* pop_integer( BasicBlock* bb );
+ 	/// @brief Generate code to push a string pointer onto the stack.
+ 	Instruction* push_string( BasicBlock* bb, const char* value );
+ 	/// @brief Generate code to pop a string pointer off the stack.
+ 	Instruction* pop_string( BasicBlock* bb );
+ 	/// @brief Generate code to get the top stack element.
+ 	Instruction* stack_top( BasicBlock* bb, Value* index );
+ 	/// @brief Generate code to get the top stack element as a string.
+ 	Instruction* stack_top_string( BasicBlock* bb, Value* index );
+ 	/// @brief Generate code to replace the top element of the stack.
+ 	Instruction* replace_top( BasicBlock* bb, Value* new_top, Value* index);
+ 
+     /// @}
+     /// @name Data Members (used during parsing)
+     /// @{
+     public:
+         static StackerCompiler*	TheInstance;	///< The instance for the parser
+ 
+     private:
+ 	std::string 		CurFilename;	///< Current file name
+ 	Module* 		TheModule; 	///< Module instance we'll build
+         Function*		TheFunction;	///< Function we're building
+ 	FunctionType* 		DefinitionType; ///< FT for Definitions
+ 	GlobalVariable*		TheStack;	///< For referencing _stack_
+ 	GlobalVariable*		TheIndex;	///< For referencing _index_
+ 	Function*		TheScanf;	///< External input function
+ 	Function*		ThePrintf;	///< External output function
+ 	Function*		TheExit;	///< External exit function
+ 	GlobalVariable*		StrFormat;	///< Format for strings
+ 	GlobalVariable*		NumFormat;	///< Format for numbers
+ 	GlobalVariable*		ChrFormat;	///< Format for chars
+ 	GlobalVariable*		InStrFormat;	///< Format for input strings
+ 	GlobalVariable*		InNumFormat;	///< Format for input numbers
+ 	GlobalVariable*		InChrFormat;	///< Format for input chars
+ 	ConstantInt*		Zero;		///< long constant 0
+ 	ConstantInt*		One;		///< long constant 1
+ 	ConstantInt*		Two;		///< long constant 2
+ 	ConstantInt*		Three;		///< long constant 3
+ 	ConstantInt*		Four;		///< long constant 4
+ 	ConstantInt*		Five;		///< long constant 5
+ 	ConstantInt*		IZero;		///< int constant 0
+ 	ConstantInt*		IOne;		///< int constant 1
+ 	ConstantInt*		ITwo;		///< int constant 2
+ 	std::vector<Value*> 	no_arguments;	///< no arguments for Stacker
+ 	bool 			echo;		///< Echo flag
+ 	size_t			stack_size;	///< Size of stack to gen.
+ 	ArrayType*		stack_type;	///< The type of the stack
+     /// @}
+ };
+ 
+ #endif


Index: llvm/projects/Stacker/lib/compiler/StackerParser.y
diff -c /dev/null llvm/projects/Stacker/lib/compiler/StackerParser.y:1.1
*** /dev/null	Sun Nov 23 11:53:05 2003
--- llvm/projects/Stacker/lib/compiler/StackerParser.y	Sun Nov 23 11:52:55 2003
***************
*** 0 ****
--- 1,190 ----
+ //===-- llvmAsmParser.y - Parser for llvm assembly files --------*- C++ -*-===//
+ // 
+ //                     The LLVM Compiler Infrastructure
+ //
+ // This file was developed by the LLVM research group and is distributed under
+ // the University of Illinois Open Source License. See LICENSE.TXT for details.
+ // 
+ //===----------------------------------------------------------------------===//
+ //
+ //  This file implements the bison parser for LLVM assembly languages files.
+ //
+ //===----------------------------------------------------------------------===//
+ 
+ %debug
+ 
+ %{
+ #include "StackerCompiler.h"
+ #include "llvm/SymbolTable.h"
+ #include "llvm/Module.h"
+ #include "llvm/iTerminators.h"
+ #include "llvm/iMemory.h"
+ #include "llvm/iOperators.h"
+ #include "llvm/iPHINode.h"
+ #include "Support/STLExtras.h"
+ #include "Support/DepthFirstIterator.h"
+ #include <list>
+ #include <utility>
+ #include <algorithm>
+ 
+ #define YYERROR_VERBOSE 1
+ #define SCI StackerCompiler::TheInstance
+ 
+ int yyerror(const char *ErrorMsg); // Forward declarations to prevent "implicit
+ int yylex();                       // declaration" of xxx warnings.
+ int yyparse();
+ 
+ %}
+ 
+ %union 
+ {
+   llvm::Module*		ModuleVal;
+   llvm::Function* 	FunctionVal;
+   llvm::BasicBlock*	BasicBlockVal;
+   uint32_t              IntegerVal;
+   char*                 StringVal;
+ }
+ 
+ /* Typed Productions */
+ %type <ModuleVal>	Module DefinitionList
+ %type <FunctionVal>	Definition ForwardDef ColonDef MainDef
+ %type <FunctionVal>	WordList
+ %type <BasicBlockVal>	Word
+ 
+ /* Typed Tokens */
+ %token <IntegerVal>	INTEGER
+ %token <StringVal>	STRING IDENTIFIER
+ 
+ /* Terminal Tokens */
+ %token 			SEMI COLON FORWARD MAIN DUMP
+ %token  		TRUE FALSE LESS MORE LESS_EQUAL MORE_EQUAL NOT_EQUAL EQUAL
+ %token 			PLUS MINUS INCR DECR MULT DIV MODULUS NEGATE ABS MIN MAX STAR_SLASH 
+ %token 			AND OR XOR LSHIFT RSHIFT 
+ %token 			DROP DROP2 NIP NIP2 DUP DUP2 SWAP SWAP2	OVER OVER2 ROT ROT2 
+ %token			RROT RROT2 TUCK TUCK2 ROLL PICK SELECT
+ %token 			MALLOC FREE GET PUT
+ %token 			IF ELSE ENDIF WHILE END RECURSE RETURN EXIT
+ %token 			TAB SPACE CR IN_STR IN_NUM IN_CHAR OUT_STR OUT_NUM OUT_CHAR
+ 
+ /* Start Token */
+ %start Module
+ 
+ %%
+ 
+ /* A module is just a DefinitionList */
+ Module 		: 				{ SCI->handle_module_start( ); } 
+ 	 	DefinitionList 			{ $$ = SCI->handle_module_end( $2 ); } ;
+ 
+ /* A Definitionlist is just a sequence of definitions */
+ DefinitionList	: DefinitionList Definition 	{ $$ = SCI->handle_definition_list_end( $1, $2 ); }
+ 		| /* empty */ 			{ $$ = SCI->handle_definition_list_start(); } ;
+ 
+ /* A definition can be one of three flavors */
+ Definition 	: ForwardDef 			{ $$ = $1; }
+ 	   	| ColonDef			{ $$ = $1; }
+ 	   	| MainDef			{ $$ = $1; } ;
+ 
+ /* Forward definitions just introduce a name */
+ ForwardDef : FORWARD IDENTIFIER SEMI 		{ $$ = SCI->handle_forward( $2 ); } ;
+ 
+ /* The main definition has to generate additional code so we treat it specially */
+ MainDef : COLON MAIN WordList SEMI		{ $$ = SCI->handle_main_definition($3); } ;
+ 
+ /* Regular definitions have a name and a WordList */
+ ColonDef : COLON IDENTIFIER WordList SEMI 	{ $$ = SCI->handle_definition( $2, $3 ); } ;
+ 
+ /* A WordList is just a sequence of words */
+ WordList : WordList Word 			{ $$ = SCI->handle_word_list_end( $1, $2 ); } 
+ 	 | /* empty */				{ $$ = SCI->handle_word_list_start() } ;
+ 
+ /* A few "words" have a funky syntax */
+ /* FIXME: The body of compound words can currently only be function calls */
+ /* This is not acceptable, it should be a WordList, but that produces a Function */
+ /* Which is hard to merge into the function the compound statement is working on */
+ Word : IF IDENTIFIER ELSE IDENTIFIER ENDIF	{ $$ = SCI->handle_if( $2, $4 ); } 
+      | IF IDENTIFIER ENDIF			{ $$ = SCI->handle_if( $2 ); } 
+      | WHILE IDENTIFIER END			{ $$ = SCI->handle_while( $2 ); } ;
+ 
+ /* A few words are handled specially */
+ Word : IDENTIFIER 				{ $$ = SCI->handle_identifier( $1 ); } ;
+ Word : STRING 					{ $$ = SCI->handle_string( $1 ); } ;
+ Word : INTEGER 					{ $$ = SCI->handle_integer( $1 ); } ;
+ 
+ /* Everything else is a terminal symbol and goes to handle_word */
+ Word : TRUE					{ $$ = SCI->handle_word( TRUE ); } ;
+ Word : FALSE					{ $$ = SCI->handle_word( FALSE ); } ;
+ Word : LESS					{ $$ = SCI->handle_word( LESS ); } ;
+ Word : MORE					{ $$ = SCI->handle_word( MORE ); } ;
+ Word : LESS_EQUAL				{ $$ = SCI->handle_word( LESS_EQUAL ); } ;
+ Word : MORE_EQUAL				{ $$ = SCI->handle_word( MORE_EQUAL ); } ;
+ Word : NOT_EQUAL				{ $$ = SCI->handle_word( NOT_EQUAL ); } ;
+ Word : EQUAL					{ $$ = SCI->handle_word( EQUAL ); } ;
+ Word : PLUS					{ $$ = SCI->handle_word( PLUS ); } ;
+ Word : MINUS					{ $$ = SCI->handle_word( MINUS ); } ;
+ Word : INCR					{ $$ = SCI->handle_word( INCR ); } ;
+ Word : DECR					{ $$ = SCI->handle_word( DECR ); } ;
+ Word : MULT					{ $$ = SCI->handle_word( MULT ); } ;
+ Word : DIV					{ $$ = SCI->handle_word( DIV ); } ;
+ Word : MODULUS					{ $$ = SCI->handle_word( MODULUS ); } ;
+ Word : NEGATE					{ $$ = SCI->handle_word( NEGATE ); } ;
+ Word : ABS					{ $$ = SCI->handle_word( ABS ); } ;
+ Word : MIN					{ $$ = SCI->handle_word( MIN ); } ;
+ Word : MAX					{ $$ = SCI->handle_word( MAX ); } ;
+ Word : STAR_SLASH				{ $$ = SCI->handle_word( STAR_SLASH ); } ;
+ Word : AND					{ $$ = SCI->handle_word( AND ); } ;
+ Word : OR					{ $$ = SCI->handle_word( OR ); } ;
+ Word : XOR					{ $$ = SCI->handle_word( XOR ); } ;
+ Word : LSHIFT					{ $$ = SCI->handle_word( LSHIFT ); } ;
+ Word : RSHIFT					{ $$ = SCI->handle_word( RSHIFT ); } ;
+ Word : DROP					{ $$ = SCI->handle_word( DROP ); } ;
+ Word : DROP2					{ $$ = SCI->handle_word( DROP2 ); } ;
+ Word : NIP					{ $$ = SCI->handle_word( NIP ); } ;
+ Word : NIP2					{ $$ = SCI->handle_word( NIP2 ); } ;
+ Word : DUP					{ $$ = SCI->handle_word( DUP ); } ;
+ Word : DUP2					{ $$ = SCI->handle_word( DUP2 ); } ;
+ Word : SWAP					{ $$ = SCI->handle_word( SWAP ); } ;
+ Word : SWAP2					{ $$ = SCI->handle_word( SWAP2 ); } ;
+ Word : OVER					{ $$ = SCI->handle_word( OVER ); } ;
+ Word : OVER2					{ $$ = SCI->handle_word( OVER2 ); } ;
+ Word : ROT					{ $$ = SCI->handle_word( ROT ); } ;
+ Word : ROT2					{ $$ = SCI->handle_word( ROT2 ); } ;
+ Word : RROT					{ $$ = SCI->handle_word( RROT ); } ;
+ Word : RROT2					{ $$ = SCI->handle_word( RROT2 ); } ;
+ Word : TUCK					{ $$ = SCI->handle_word( TUCK ); } ;
+ Word : TUCK2					{ $$ = SCI->handle_word( TUCK2 ); } ;
+ Word : ROLL					{ $$ = SCI->handle_word( ROLL ); } ;
+ Word : PICK					{ $$ = SCI->handle_word( PICK ); } ;
+ Word : SELECT					{ $$ = SCI->handle_word( SELECT ); } ;
+ Word : MALLOC					{ $$ = SCI->handle_word( MALLOC ); } ;
+ Word : FREE					{ $$ = SCI->handle_word( FREE ); } ;
+ Word : GET					{ $$ = SCI->handle_word( GET ); } ;
+ Word : PUT					{ $$ = SCI->handle_word( PUT ); } ;
+ Word : RECURSE					{ $$ = SCI->handle_word( RECURSE ); } ;
+ Word : RETURN					{ $$ = SCI->handle_word( RETURN ); } ;
+ Word : EXIT					{ $$ = SCI->handle_word( EXIT ); } ;
+ Word : TAB					{ $$ = SCI->handle_word( TAB ); };
+ Word : SPACE					{ $$ = SCI->handle_word( SPACE ); } ;
+ Word : CR					{ $$ = SCI->handle_word( CR ); } ;
+ Word : IN_STR					{ $$ = SCI->handle_word( IN_STR ); } ;
+ Word : IN_NUM					{ $$ = SCI->handle_word( IN_NUM ); } ;
+ Word : IN_CHAR					{ $$ = SCI->handle_word( IN_CHAR ); } ;
+ Word : OUT_STR					{ $$ = SCI->handle_word( OUT_STR ); } ;
+ Word : OUT_NUM					{ $$ = SCI->handle_word( OUT_NUM ); } ;
+ Word : OUT_CHAR					{ $$ = SCI->handle_word( OUT_CHAR ); } ;
+ Word : DUMP					{ $$ = SCI->handle_word( DUMP ); } ;
+ 
+ %%
+ 
+ /* Handle messages a little more nicely than the default yyerror */
+ int yyerror(const char *ErrorMsg) {
+   std::string where 
+     = std::string((SCI->filename() == "-") ? std::string("<stdin>") : SCI->filename())
+                   + ":" + utostr((unsigned) Stackerlineno ) + ": ";
+   std::string errMsg = std::string(ErrorMsg) + "\n" + where + " while reading ";
+   if (yychar == YYEMPTY)
+     errMsg += "end-of-file.";
+   else
+     errMsg += "token: '" + std::string(Stackertext, Stackerleng) + "'";
+   StackerCompiler::ThrowException(errMsg);
+   return 0;
+ }





More information about the llvm-commits mailing list