//
// Copyright(c) 2001 Simon Howard
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of version 2 of the GNU General Public License
// as published by the Free Software Foundation.
// 
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
// 
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//
//------------------------------------------------------------------------------
//
// Output print functions for MS IL (.Net)
//
//------------------------------------------------------------------------------

#include "parser.h"

#define ARRAY_SIZE 8000

void print_plusnode(treenode_t *node, FILE *fstream)
{
	fprintf(fstream,
		// 2nd arguments for write back
		
		"\t\tldloc bfarray\n"
		"\t\tldloc bfarrayloc\n"
		"\n"
		// load value
		
		"\t\tldloc bfarray\n"                // array
		"\t\tldloc bfarrayloc\n"             // index
		"\t\tldelem.i4\n"                  // load

		// add 1

		"\t\tldc.i4.1\n"
		"\t\tadd\n"                        // add 1
		"\n"
		"\t\tstelem.i4\n"                  // save
		"\n"
		);
}

void print_minusnode(treenode_t *node, FILE *fstream)
{
	fprintf(fstream,
		// 2nd arguments for write back

		"\t\tldloc bfarray\n"
		"\t\tldloc bfarrayloc\n"
		"\n"
		// load value
		
		"\t\tldloc bfarray\n"                // array
		"\t\tldloc bfarrayloc\n"             // index
		"\t\tldelem.i4\n"                  // load

		// subtract 1

		"\t\tldc.i4.1\n"
		"\t\tsub\n"                        // subtract 1
		"\n"
		"\t\tstelem.i4\n"                  // save
		"\n"
		);
	
}

void print_prevnode(treenode_t *node, FILE *fstream)
{
	fprintf(fstream,
		"\t\tldloc bfarrayloc\n"
		"\t\tldc.i4.1\n"
		"\t\tadd\n"
		"\t\tstloc bfarrayloc\n"
		"\n"
		);
}

void print_nextnode(treenode_t *node, FILE *fstream)
{
	fprintf(fstream,
		"\t\tldloc bfarrayloc\n"
		"\t\tldc.i4.1\n"
		"\t\tsub\n"
		"\t\tstloc bfarrayloc\n"
		"\n"
		);
}

void print_loopnode(treenode_t *node, FILE *fstream)
{
	loopnode_t *loop = (loopnode_t *) node->data;
	
	fprintf(fstream,
		"\tloop%istart:\n",
		loop->loop_num);

	// check current value under pointer is non-zero

	fprintf(fstream,
		"\t\tldloc bfarray\n"
		"\t\tldloc bfarrayloc\n"
		"\t\tldelem.i4\n"
		"\t\tbrfalse loop%iend\n"
		"\n",
		loop->loop_num);

	loop->list->print(loop->list, fstream);
	
	fprintf(fstream,
		"\t\tbr loop%istart\n"
		"\tloop%iend:\n"
		"\n",
		loop->loop_num,
		loop->loop_num);
		
}

void print_readnode(treenode_t *node, FILE *fstream)
{
	fprintf(fstream,
		"\t\tldloc bfarray\n"
		"\t\tldloc bfarrayloc\n"
		"\t\tcall int32 [mscorlib] System.Console::Read()\n"
		"\t\tstelem.i4\n"
		"\n"
		);
}

void print_printnode(treenode_t *node, FILE *fstream)
{
	fprintf(fstream,
		"\t\tldloc bfarray\n"
		"\t\tldloc bfarrayloc\n"
		"\t\tldelem.i4\n"
		"\t\tcall void [mscorlib] System.Console::Write(char)\n"
		"\n"
		);
		
}

// start of file

void print_head(FILE *fstream)
{
	fprintf(fstream,
		".assembly extern mscorlib {}\n"
		".class public hello extends [mscorlib] System.Object {\n"
		"\t.method static public void main() il managed {\n"
		"\t\t.maxstack 10\n"
		"\t\t.entrypoint\n"
		"\t\t.locals (int32[] bfarray, int32 bfarrayloc)\n"
		"\n"
		);

	fprintf(fstream,
		"\t\tldc.i4.s %i\n"
		"\t\tnewarr int32\n"
		"\t\tstloc bfarray\n"
		"\n",
		ARRAY_SIZE
		);

	fprintf(fstream,
		"\t\tldc.i4.s %i\n"
		"\t\tstloc bfarrayloc\n"
		"\n",
		ARRAY_SIZE / 2
		);
}

// end of file

void print_tail(FILE *fstream)
{
	fprintf(fstream,
		"\t\tret\n"
		"\t}\n"
		"}\n"
		"\n"
		);
}
       
