PageRenderTime 221ms CodeModel.GetById 3ms app.highlight 200ms RepoModel.GetById 1ms app.codeStats 1ms

/indra/lscript/lscript_compile/lscript_tree.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 2002 lines | 1954 code | 19 blank | 29 comment | 4 complexity | 9a642e4b3c4c6c134920499e3410d98b MD5 | raw file

Large files files are truncated, but you can click here to view the full file

   1/** 
   2 * @file lscript_tree.cpp
   3 * @brief implements methods for lscript_tree.h classes
   4 *
   5 * $LicenseInfo:firstyear=2002&license=viewerlgpl$
   6 * Second Life Viewer Source Code
   7 * Copyright (C) 2010, Linden Research, Inc.
   8 * 
   9 * This library is free software; you can redistribute it and/or
  10 * modify it under the terms of the GNU Lesser General Public
  11 * License as published by the Free Software Foundation;
  12 * version 2.1 of the License only.
  13 * 
  14 * This library is distributed in the hope that it will be useful,
  15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  17 * Lesser General Public License for more details.
  18 * 
  19 * You should have received a copy of the GNU Lesser General Public
  20 * License along with this library; if not, write to the Free Software
  21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  22 * 
  23 * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
  24 * $/LicenseInfo$
  25 */
  26
  27// TO DO: Move print functionality from .h file to here
  28
  29#include "linden_common.h"
  30
  31#include "lscript_tree.h"
  32#include "lscript_typecheck.h"
  33#include "lscript_resource.h"
  34#include "lscript_bytecode.h"
  35#include "lscript_heap.h"
  36#include "lscript_library.h"
  37#include "lscript_alloc.h"
  38
  39//#define LSL_INCLUDE_DEBUG_INFO
  40
  41
  42static void print_cil_box(LLFILE* fp, LSCRIPTType type)
  43{
  44	
  45switch(type)
  46	{
  47	case LST_INTEGER:
  48		fprintf(fp, "box [mscorlib]System.Int32\n");
  49		break;
  50	case LST_FLOATINGPOINT:
  51		fprintf(fp, "box [mscorlib]System.Single\n");
  52		break;
  53	case LST_STRING:
  54		// System.String is not a System.ValueType,
  55		// so does not need to be boxed.
  56		break;
  57	case LST_KEY:
  58		fprintf(fp, "box [ScriptTypes]LindenLab.SecondLife.Key\n");
  59		break;
  60	case LST_VECTOR:
  61		fprintf(fp, "box [ScriptTypes]LindenLab.SecondLife.Vector\n");
  62		break;
  63	case LST_QUATERNION:
  64		fprintf(fp, "box [ScriptTypes]LindenLab.SecondLife.Quaternion\n");
  65		break;
  66	default:
  67		llassert(false);
  68		break;
  69	}
  70}
  71
  72static void print_cil_type(LLFILE* fp, LSCRIPTType type)
  73{
  74	switch(type)
  75	{
  76	case LST_INTEGER:
  77		fprintf(fp, "int32");
  78		break;
  79	case LST_FLOATINGPOINT:
  80		fprintf(fp, "float32");
  81		break;
  82	case LST_STRING:
  83		fprintf(fp, "string");
  84		break;		
  85	case LST_KEY:
  86		fprintf(fp, "valuetype [ScriptTypes]LindenLab.SecondLife.Key");
  87		break;
  88	case LST_VECTOR:
  89		fprintf(fp, "class [ScriptTypes]LindenLab.SecondLife.Vector");
  90		break;
  91	case LST_QUATERNION:
  92		fprintf(fp, "class [ScriptTypes]LindenLab.SecondLife.Quaternion");
  93		break;
  94	case LST_LIST:
  95		fprintf(fp, "class [mscorlib]System.Collections.ArrayList");
  96		break;
  97	case LST_NULL:
  98		fprintf(fp, "void");
  99		break;
 100	default:
 101		break;
 102	}
 103}
 104
 105void LLScriptType::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCompilePass pass, LSCRIPTPruneType ptype, BOOL &prunearg, LLScriptScope *scope, LSCRIPTType &type, LSCRIPTType basetype, U64 &count, LLScriptByteCodeChunk *chunk, LLScriptByteCodeChunk *heap, S32 stacksize, LLScriptScopeEntry *entry, S32 entrycount, LLScriptLibData **ldata)
 106{
 107	if (gErrorToText.getErrors())
 108	{
 109		return;
 110	}
 111	switch(pass)
 112	{
 113	case LSCP_PRETTY_PRINT:
 114	case LSCP_EMIT_ASSEMBLY:
 115		fprintf(fp,"%s",LSCRIPTTypeNames[mType]);
 116		break;
 117	case LSCP_TYPE:
 118		type = mType;
 119		break;
 120	case LSCP_EMIT_CIL_ASSEMBLY:
 121		print_cil_type(fp, mType);
 122		break;
 123	default:
 124		break;
 125	}
 126}
 127
 128S32 LLScriptType::getSize()
 129{
 130	return LSCRIPTDataSize[mType];
 131}
 132
 133void LLScriptConstant::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCompilePass pass, LSCRIPTPruneType ptype, BOOL &prunearg, LLScriptScope *scope, LSCRIPTType &type, LSCRIPTType basetype, U64 &count, LLScriptByteCodeChunk *chunk, LLScriptByteCodeChunk *heap, S32 stacksize, LLScriptScopeEntry *entry, S32 entrycount, LLScriptLibData **ldata)
 134{
 135	if (gErrorToText.getErrors())
 136	{
 137		return;
 138	}
 139	switch(pass)
 140	{
 141	case LSCP_PRETTY_PRINT:
 142	case LSCP_EMIT_ASSEMBLY:
 143		fprintf(fp,"Script Constant Base class -- should never get here!\n");
 144		break;
 145	default:
 146		break;
 147	}
 148}
 149
 150S32 LLScriptConstant::getSize()
 151{
 152	printf("Script Constant Base class -- should never get here!\n");
 153	return 0;
 154}
 155
 156
 157
 158void LLScriptConstantInteger::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCompilePass pass, LSCRIPTPruneType ptype, BOOL &prunearg, LLScriptScope *scope, LSCRIPTType &type, LSCRIPTType basetype, U64 &count, LLScriptByteCodeChunk *chunk, LLScriptByteCodeChunk *heap, S32 stacksize, LLScriptScopeEntry *entry, S32 entrycount, LLScriptLibData **ldata)
 159{
 160	if (gErrorToText.getErrors())
 161	{
 162		return;
 163	}
 164	switch(pass)
 165	{
 166	case LSCP_PRETTY_PRINT:
 167		fprintf(fp, "%d", mValue);
 168		break;
 169	case LSCP_EMIT_ASSEMBLY:
 170		fprintf(fp, "PUSHARGI %d\n", mValue);
 171		break;
 172	case LSCP_TYPE:
 173		type = mType;
 174		break;
 175	case LSCP_EMIT_BYTE_CODE:
 176		{
 177			chunk->addInteger(mValue);
 178			type = mType;
 179		}
 180		break;
 181	case LSCP_TO_STACK:
 182		{
 183			chunk->addByte(LSCRIPTOpCodes[LOPC_PUSHARGI]);
 184			chunk->addInteger(mValue);
 185			type = mType;
 186		}
 187		break;
 188	case LSCP_LIST_BUILD_SIMPLE:
 189		{
 190			*ldata = new LLScriptLibData(mValue);
 191		}
 192		break;
 193	case LSCP_EMIT_CIL_ASSEMBLY:
 194		fprintf(fp, "ldc.i4 %d\n", mValue);
 195		type = mType;
 196		break;
 197	default:
 198		break;
 199	}
 200}
 201
 202S32 LLScriptConstantInteger::getSize()
 203{
 204	return LSCRIPTDataSize[LST_INTEGER];
 205}
 206
 207void LLScriptConstantFloat::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCompilePass pass, LSCRIPTPruneType ptype, BOOL &prunearg, LLScriptScope *scope, LSCRIPTType &type, LSCRIPTType basetype, U64 &count, LLScriptByteCodeChunk *chunk, LLScriptByteCodeChunk *heap, S32 stacksize, LLScriptScopeEntry *entry, S32 entrycount, LLScriptLibData **ldata)
 208{
 209	if (gErrorToText.getErrors())
 210	{
 211		return;
 212	}
 213	switch(pass)
 214	{
 215	case LSCP_PRETTY_PRINT:
 216		fprintf(fp, "%5.5f", mValue);
 217		break;
 218	case LSCP_EMIT_ASSEMBLY:
 219		fprintf(fp, "PUSHARGF %5.5f\n", mValue);
 220		break;
 221	case LSCP_TYPE:
 222		type = mType;
 223		break;
 224	case LSCP_EMIT_BYTE_CODE:
 225		{
 226			chunk->addFloat(mValue);
 227			type = mType;
 228		}
 229		break;
 230	case LSCP_TO_STACK:
 231		{
 232			chunk->addByte(LSCRIPTOpCodes[LOPC_PUSHARGF]);
 233			chunk->addFloat(mValue);
 234			type = mType;
 235		}
 236		break;
 237	case LSCP_LIST_BUILD_SIMPLE:
 238		{
 239			*ldata = new LLScriptLibData(mValue);
 240		}
 241		break;
 242	case LSCP_EMIT_CIL_ASSEMBLY:
 243	        {
 244		        double v = (double)mValue;
 245			U8 * p = (U8 *)&v; // See ECMA-335 Partition VI, Appendix C.4.6 Examples, line 4
 246			fprintf(fp, "ldc.r8 (%02x %02x %02x %02x %02x %02x %02x %02x)\n", p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]);
 247			type = mType;
 248		}
 249		break;
 250	default:
 251		break;
 252	}
 253}
 254
 255S32 LLScriptConstantFloat::getSize()
 256{
 257	return LSCRIPTDataSize[LST_FLOATINGPOINT];
 258}
 259
 260void print_escaped(LLFILE* fp, const char* str)
 261{
 262  putc('"', fp);
 263  for(const char* c = str; *c != '\0'; ++c)
 264  {
 265	  switch(*c)
 266	  {
 267	  case '"':
 268		putc('\\', fp);
 269		putc(*c, fp);
 270		break;
 271	  case '\n':
 272		putc('\\', fp);
 273		putc('n', fp);
 274		break;
 275	  case '\t':
 276		putc(' ', fp);
 277		putc(' ', fp);
 278		putc(' ', fp);
 279		putc(' ', fp);
 280		break;
 281	  case '\\':
 282		putc('\\', fp);
 283		putc('\\', fp);
 284		break;
 285	  default:
 286		putc(*c, fp);
 287	  }
 288  }
 289  putc('"', fp);
 290}
 291
 292void LLScriptConstantString::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCompilePass pass, LSCRIPTPruneType ptype, BOOL &prunearg, LLScriptScope *scope, LSCRIPTType &type, LSCRIPTType basetype, U64 &count, LLScriptByteCodeChunk *chunk, LLScriptByteCodeChunk *heap, S32 stacksize, LLScriptScopeEntry *entry, S32 entrycount, LLScriptLibData **ldata)
 293{
 294	if (gErrorToText.getErrors())
 295	{
 296		return;
 297	}
 298	switch(pass)
 299	{
 300	case LSCP_PRETTY_PRINT:
 301		fprintf(fp, "\"%s\"", mValue);
 302		break;
 303	case LSCP_EMIT_ASSEMBLY:
 304		fprintf(fp, "PUSHARGS \"%s\"\n", mValue);
 305		break;
 306	case LSCP_TYPE:
 307		type = mType;
 308		break;
 309	case LSCP_EMIT_BYTE_CODE:
 310		{
 311			chunk->addInteger(heap->mCurrentOffset + 1);
 312			LLScriptLibData *data = new LLScriptLibData(mValue);
 313			U8 *temp;
 314			S32 size = lsa_create_data_block(&temp, data, heap->mCurrentOffset);
 315
 316			heap->addBytes(temp, size);
 317			delete [] temp;
 318			delete data;
 319		}
 320		break;
 321	case LSCP_TO_STACK:
 322		{
 323			chunk->addByte(LSCRIPTOpCodes[LOPC_PUSHARGS]);
 324			chunk->addBytes(mValue, (S32)strlen(mValue) + 1);
 325			type = mType;
 326		}
 327		break;
 328	case LSCP_LIST_BUILD_SIMPLE:
 329		{
 330			*ldata = new LLScriptLibData(mValue);
 331		}
 332		break;
 333	case LSCP_EMIT_CIL_ASSEMBLY:
 334		fprintf(fp, "ldstr ");
 335		print_escaped(fp, mValue);
 336		fprintf(fp, "\n");
 337	default:
 338		break;
 339	}
 340}
 341
 342S32 LLScriptConstantString::getSize()
 343{
 344	return (S32)strlen(mValue) + 1;
 345}
 346
 347void LLScriptIdentifier::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCompilePass pass, LSCRIPTPruneType ptype, BOOL &prunearg, LLScriptScope *scope, LSCRIPTType &type, LSCRIPTType basetype, U64 &count, LLScriptByteCodeChunk *chunk, LLScriptByteCodeChunk *heap, S32 stacksize, LLScriptScopeEntry *entry, S32 entrycount, LLScriptLibData **ldata)
 348{
 349	if (gErrorToText.getErrors())
 350	{
 351		return;
 352	}
 353	switch(pass)
 354	{
 355	case LSCP_PRETTY_PRINT:
 356		fprintf(fp, "%s", mName);
 357		break;
 358	case LSCP_EMIT_ASSEMBLY:
 359		if (mScopeEntry)
 360		{
 361			if (mScopeEntry->mIDType == LIT_VARIABLE)
 362			{
 363				fprintf(fp, "$BP + %d [%s]", mScopeEntry->mOffset, mName);
 364			}
 365			else if (mScopeEntry->mIDType == LIT_GLOBAL)
 366			{
 367				fprintf(fp, "$GVR + %d [%s]", mScopeEntry->mOffset, mName);
 368			}
 369			else
 370			{
 371				fprintf(fp, "%s", mName);
 372			}
 373		}
 374		break;
 375	case LSCP_TYPE:
 376		if (mScopeEntry)
 377			type = mScopeEntry->mType;
 378		else
 379			type = LST_NULL;
 380		break;
 381	case LSCP_RESOURCE:
 382		if (mScopeEntry)
 383		{
 384			if (mScopeEntry->mIDType == LIT_VARIABLE)
 385			{
 386//				fprintf(fp, "LOCAL : %d : %d : %s\n", mScopeEntry->mOffset, mScopeEntry->mSize, mName);
 387			}
 388			else if (mScopeEntry->mIDType == LIT_GLOBAL)
 389			{
 390//				fprintf(fp, "GLOBAL: %d : %d : %s\n", mScopeEntry->mOffset, mScopeEntry->mSize, mName);
 391			}
 392		}
 393		break;
 394	case LSCP_LIST_BUILD_SIMPLE:
 395		{
 396			if (mScopeEntry)
 397			{
 398				if (mScopeEntry->mType == LST_LIST)
 399				{
 400					gErrorToText.writeError(fp, this, LSERROR_NO_LISTS_IN_LISTS);
 401				}
 402				else if (mScopeEntry->mAssignable)
 403				{
 404					mScopeEntry->mAssignable->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, ldata);
 405				}
 406				else
 407				{
 408					gErrorToText.writeError(fp, this, LSERROR_NO_UNITIALIZED_VARIABLES_IN_LISTS);
 409				}
 410			}
 411			else
 412			{
 413				gErrorToText.writeError(fp, this, LSERROR_UNDEFINED_NAME);
 414			}
 415		}
 416		break;
 417	case LSCP_EMIT_CIL_ASSEMBLY:
 418		fprintf(fp, "'%s'", mName);
 419		break;
 420	default:
 421		break;
 422	}
 423}
 424
 425S32 LLScriptIdentifier::getSize()
 426{
 427	
 428	return 0;
 429}
 430
 431
 432
 433void LLScriptSimpleAssignable::addAssignable(LLScriptSimpleAssignable *assign)
 434{
 435	if (mNextp)
 436	{
 437		assign->mNextp = mNextp;
 438	}
 439	mNextp = assign;
 440}
 441
 442void LLScriptSimpleAssignable::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCompilePass pass, LSCRIPTPruneType ptype, BOOL &prunearg, LLScriptScope *scope, LSCRIPTType &type, LSCRIPTType basetype, U64 &count, LLScriptByteCodeChunk *chunk, LLScriptByteCodeChunk *heap, S32 stacksize, LLScriptScopeEntry *entry, S32 entrycount, LLScriptLibData **ldata)
 443{
 444	if (gErrorToText.getErrors())
 445	{
 446		return;
 447	}
 448	fprintf(fp, "Simple Assignable Base Class -- should never get here!\n");
 449}
 450
 451S32 LLScriptSimpleAssignable::getSize()
 452{
 453	
 454	printf("Simple Assignable Base Class -- should never get here!\n");
 455	return 0;
 456}
 457
 458static void print_cil_member(LLFILE* fp, LLScriptIdentifier *ident)
 459{
 460	print_cil_type(fp, ident->mScopeEntry->mType);
 461	fprintf(fp, " %s::'%s'\n", gScriptp->getClassName(), ident->mScopeEntry->mIdentifier);
 462}
 463
 464void LLScriptSAIdentifier::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCompilePass pass, LSCRIPTPruneType ptype, BOOL &prunearg, LLScriptScope *scope, LSCRIPTType &type, LSCRIPTType basetype, U64 &count, LLScriptByteCodeChunk *chunk, LLScriptByteCodeChunk *heap, S32 stacksize, LLScriptScopeEntry *entry, S32 entrycount, LLScriptLibData **ldata)
 465{
 466	if (gErrorToText.getErrors())
 467	{
 468		return;
 469	}
 470	switch(pass)
 471	{
 472	case LSCP_PRETTY_PRINT:
 473	case LSCP_EMIT_ASSEMBLY:
 474		mIdentifier->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
 475		if (mNextp)
 476		{
 477			fprintf(fp, ", ");
 478			mNextp->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
 479		}
 480		break;
 481	case LSCP_SCOPE_PASS1:
 482		{ 
 483			LLScriptScopeEntry *entry = scope->findEntry(mIdentifier->mName);
 484			if (!entry)
 485			{
 486				gErrorToText.writeError(fp, this, LSERROR_UNDEFINED_NAME);
 487			}
 488			else
 489			{
 490				// if we did find it, make sure this identifier is associated with the correct scope entry
 491				mIdentifier->mScopeEntry = entry;
 492			}
 493			if (mNextp)
 494			{
 495				mNextp->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
 496			}
 497		}
 498		break;
 499	case LSCP_EMIT_BYTE_CODE:
 500		{
 501			if (mIdentifier->mScopeEntry)
 502			{
 503				if(mIdentifier->mScopeEntry->mAssignable)
 504				{
 505					mIdentifier->mScopeEntry->mAssignable->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
 506				}
 507				else
 508				{
 509					// Babbage: 29/8/06: If the scope entry has no mAssignable,
 510					// set the default type and add the default 0 value to the 
 511					// chunk. Without this SAVectors and SAQuaternions will 
 512					// assume the arbitrary current type is the assignable type 
 513					// and may attempt to access a null chunk. (SL-20156)
 514					type = mIdentifier->mScopeEntry->mType;
 515					chunk->addBytes(LSCRIPTDataSize[type]);
 516				}
 517			}
 518			if (mNextp)
 519			{
 520				mNextp->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
 521			}
 522		}
 523		break;
 524	case LSCP_LIST_BUILD_SIMPLE:
 525		{
 526			mIdentifier->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, ldata);
 527			if (mNextp)
 528			{
 529				mNextp->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, &(*ldata)->mListp);
 530			}
 531		}
 532		break;
 533
 534	case LSCP_EMIT_CIL_ASSEMBLY:
 535		{
 536			fprintf(fp, "ldarg.0\n");
 537			fprintf(fp, "ldfld ");
 538			print_cil_member(fp, mIdentifier);
 539			fprintf(fp, "\n");
 540			if (mNextp)
 541			{
 542				mNextp->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
 543			}
 544			break;
 545		}
 546	default:
 547		mIdentifier->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
 548		if (mNextp)
 549		{
 550			mNextp->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
 551		}
 552		break;
 553	}
 554}
 555
 556S32 LLScriptSAIdentifier::getSize()
 557{
 558	return mIdentifier->getSize();
 559}
 560
 561void LLScriptSAConstant::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCompilePass pass, LSCRIPTPruneType ptype, BOOL &prunearg, LLScriptScope *scope, LSCRIPTType &type, LSCRIPTType basetype, U64 &count, LLScriptByteCodeChunk *chunk, LLScriptByteCodeChunk *heap, S32 stacksize, LLScriptScopeEntry *entry, S32 entrycount, LLScriptLibData **ldata)
 562{
 563	if (gErrorToText.getErrors())
 564	{
 565		return;
 566	}
 567	switch(pass)
 568	{
 569	case LSCP_PRETTY_PRINT:
 570	case LSCP_EMIT_ASSEMBLY:
 571		mConstant->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
 572		if (mNextp)
 573		{
 574			fprintf(fp, ", ");
 575			mNextp->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
 576		}
 577		break;
 578	case LSCP_LIST_BUILD_SIMPLE:
 579		{
 580			mConstant->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, ldata);
 581			if (mNextp)
 582			{
 583				mNextp->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, &(*ldata)->mListp);
 584			}
 585		}
 586		break;
 587	default:
 588		mConstant->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
 589		if (mNextp)
 590		{
 591			mNextp->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
 592		}
 593		break;
 594	}
 595}
 596
 597S32 LLScriptSAConstant::getSize()
 598{
 599	return mConstant->getSize();
 600}
 601
 602
 603static void print_cil_cast(LLFILE* fp, LSCRIPTType srcType, LSCRIPTType targetType)
 604{
 605	switch(srcType)
 606	{
 607	case LST_INTEGER:
 608		switch(targetType)
 609		{
 610		case LST_FLOATINGPOINT:
 611			fprintf(fp, "conv.r8\n");
 612			break;
 613		case LST_STRING:
 614			fprintf(fp, "call string class [mscorlib]System.Convert::ToString(int32)\n");
 615			break;
 616		case LST_LIST:
 617			print_cil_box(fp, LST_INTEGER);
 618			fprintf(fp, "call class [mscorlib]System.Collections.ArrayList class [LslUserScript]LindenLab.SecondLife.LslUserScript::CreateList(object)\n");
 619			break;
 620		default:
 621			break;
 622		}
 623		break;
 624	case LST_FLOATINGPOINT:
 625		switch(targetType)
 626		{
 627		case LST_INTEGER:
 628			fprintf(fp, "call int32 [LslLibrary]LindenLab.SecondLife.LslRunTime::ToInteger(float32)\n");
 629			break;
 630		case LST_STRING:
 631			fprintf(fp, "call string [LslLibrary]LindenLab.SecondLife.LslRunTime::ToString(float32)\n");
 632			break;
 633		case LST_LIST:
 634			print_cil_box(fp, LST_FLOATINGPOINT);
 635			fprintf(fp, "call class [mscorlib]System.Collections.ArrayList class [LslUserScript]LindenLab.SecondLife.LslUserScript::CreateList(object)\n");
 636			break;
 637		default:
 638			break;
 639		}
 640		break;
 641	case LST_STRING:
 642		switch(targetType)
 643		{
 644		case LST_INTEGER:
 645			fprintf(fp, "call int32 [LslLibrary]LindenLab.SecondLife.LslRunTime::StringToInt(string)\n");
 646			break;
 647		case LST_FLOATINGPOINT:
 648			fprintf(fp, "call float32 [LslLibrary]LindenLab.SecondLife.LslRunTime::StringToFloat(string)\n");
 649			break;
 650		case LST_KEY:
 651			fprintf(fp, "call valuetype [ScriptTypes]LindenLab.SecondLife.Key class [LslUserScript]LindenLab.SecondLife.LslUserScript::'CreateKey'(string)\n");
 652			break;	
 653		case LST_LIST:
 654			fprintf(fp, "call class [mscorlib]System.Collections.ArrayList class [LslUserScript]LindenLab.SecondLife.LslUserScript::CreateList(object)\n");
 655			break;
 656		case LST_VECTOR:
 657			fprintf(fp, "call class [ScriptTypes]LindenLab.SecondLife.Vector class [LslUserScript]LindenLab.SecondLife.LslUserScript::'ParseVector'(string)\n");
 658			break;
 659		case LST_QUATERNION:
 660			fprintf(fp, "call class [ScriptTypes]LindenLab.SecondLife.Quaternion class [LslUserScript]LindenLab.SecondLife.LslUserScript::'ParseQuaternion'(string)\n");
 661			break;
 662		default:
 663			break;
 664		}
 665		break;
 666	case LST_KEY:
 667		switch(targetType)
 668		{
 669		case LST_KEY:
 670			break;
 671		case LST_STRING:
 672			fprintf(fp, "call string [LslUserScript]LindenLab.SecondLife.LslUserScript::'ToString'(valuetype [ScriptTypes]LindenLab.SecondLife.Key)\n");
 673			break;
 674		case LST_LIST:
 675			print_cil_box(fp, LST_KEY);
 676			fprintf(fp, "call class [mscorlib]System.Collections.ArrayList class [LslUserScript]LindenLab.SecondLife.LslUserScript::CreateList(object)\n");
 677			break;
 678		default:
 679			break;
 680		}
 681		break;
 682	case LST_VECTOR:
 683		switch(targetType)
 684		{
 685		case LST_VECTOR:
 686			break;
 687		case LST_STRING:
 688			fprintf(fp, "call string [LslUserScript]LindenLab.SecondLife.LslUserScript::'ToString'(valuetype [ScriptTypes]LindenLab.SecondLife.Vector)\n");
 689			break;
 690		case LST_LIST:
 691			print_cil_box(fp, LST_VECTOR);
 692			fprintf(fp, "call class [mscorlib]System.Collections.ArrayList class [LslUserScript]LindenLab.SecondLife.LslUserScript::CreateList(object)\n");
 693			break;
 694		default:
 695			break;
 696		}
 697		break;
 698	case LST_QUATERNION:
 699		switch(targetType)
 700		{
 701		case LST_QUATERNION:
 702			break;
 703		case LST_STRING:
 704			fprintf(fp, "call string [LslUserScript]LindenLab.SecondLife.LslUserScript::'ToString'(valuetype [ScriptTypes]LindenLab.SecondLife.Quaternion)\n");
 705			break;
 706		case LST_LIST:
 707			print_cil_box(fp, LST_QUATERNION);
 708			fprintf(fp, "call class [mscorlib]System.Collections.ArrayList class [LslUserScript]LindenLab.SecondLife.LslUserScript::CreateList(object)\n");
 709			break;
 710		default:
 711			break;
 712		}
 713		break;
 714	case LST_LIST:
 715		switch(targetType)
 716		{
 717		case LST_LIST:
 718			break;
 719		case LST_STRING:
 720			fprintf(fp, "call string [LslLibrary]LindenLab.SecondLife.LslRunTime::ListToString(class [mscorlib]System.Collections.ArrayList)\n");
 721			break;
 722		default:
 723			break;
 724		}
 725		break;
 726	default:
 727		break;
 728	}
 729}
 730
 731static void print_cil_numeric_cast(LLFILE* fp, LSCRIPTType currentArg, LSCRIPTType otherArg)
 732{
 733	if((currentArg == LST_INTEGER) && ((otherArg == LST_FLOATINGPOINT) || (otherArg == LST_VECTOR)))
 734	{
 735		print_cil_cast(fp, LST_INTEGER, LST_FLOATINGPOINT);
 736	}
 737}
 738
 739static void print_cil_assignment_cast(LLFILE* fp, LSCRIPTType src,
 740									  LSCRIPTType dest)
 741{
 742	if (LST_STRING == src && LST_KEY == dest)
 743	{
 744		print_cil_cast(fp, src, dest);
 745	}
 746	else if(LST_KEY == src && LST_STRING == dest)
 747	{
 748		print_cil_cast(fp, src, dest);
 749	}
 750	else
 751	{
 752		print_cil_numeric_cast(fp, src, dest);
 753	}
 754}
 755 
 756// HACK! Babbage: should be converted to virtual on LSCRIPTSimpleAssignableType to avoid downcasts.
 757LSCRIPTType get_type(LLScriptSimpleAssignable* sa)
 758{
 759	LSCRIPTType result = LST_NULL;
 760	switch(sa->mType)
 761	{
 762	case LSSAT_IDENTIFIER:
 763		result = ((LLScriptSAIdentifier*) sa)->mIdentifier->mScopeEntry->mType;
 764		break;
 765	case LSSAT_CONSTANT:
 766		result = ((LLScriptSAConstant*) sa)->mConstant->mType;
 767		break;
 768	case LSSAT_VECTOR_CONSTANT:
 769		result = LST_VECTOR;
 770		break;
 771	case LSSAT_QUATERNION_CONSTANT:
 772		result = LST_QUATERNION;
 773		break;
 774	case LSSAT_LIST_CONSTANT:
 775		result = LST_LIST;
 776		break;
 777	default:
 778		result = LST_UNDEFINED;
 779		break;
 780	}
 781	return result;
 782}
 783
 784void LLScriptSAVector::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCompilePass pass, LSCRIPTPruneType ptype, BOOL &prunearg, LLScriptScope *scope, LSCRIPTType &type, LSCRIPTType basetype, U64 &count, LLScriptByteCodeChunk *chunk, LLScriptByteCodeChunk *heap, S32 stacksize, LLScriptScopeEntry *entry, S32 entrycount, LLScriptLibData **ldata)
 785{
 786	if (gErrorToText.getErrors())
 787	{
 788		return;
 789	}
 790	switch(pass)
 791	{
 792	case LSCP_PRETTY_PRINT:
 793	case LSCP_EMIT_ASSEMBLY:
 794		fprintf(fp, "< ");
 795		mEntry3->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
 796		fprintf(fp, ", ");
 797		mEntry2->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
 798		fprintf(fp, ", ");
 799		mEntry1->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
 800		fprintf(fp, " >");
 801		if (mNextp)
 802		{
 803			fprintf(fp, ", ");
 804			mNextp->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
 805		}
 806		break;
 807	case LSCP_TYPE:
 808		// vector's take floats
 809		mEntry3->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
 810		if (!legal_assignment(LST_FLOATINGPOINT, type))
 811		{
 812			gErrorToText.writeError(fp, this, LSERROR_TYPE_MISMATCH);
 813		}
 814		mEntry2->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
 815		if (!legal_assignment(LST_FLOATINGPOINT, type))
 816		{
 817			gErrorToText.writeError(fp, this, LSERROR_TYPE_MISMATCH);
 818		}
 819		mEntry1->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
 820		if (!legal_assignment(LST_FLOATINGPOINT, type))
 821		{
 822			gErrorToText.writeError(fp, this, LSERROR_TYPE_MISMATCH);
 823		}
 824		type = LST_VECTOR;
 825		if (mNextp)
 826		{
 827			mNextp->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
 828		}
 829		break;
 830	case LSCP_EMIT_BYTE_CODE:
 831		mEntry3->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
 832		if (type == LST_INTEGER)
 833		{
 834			S32 offset = chunk->mCurrentOffset - 4;
 835			bytestream_int2float(chunk->mCodeChunk, offset);
 836		}
 837		mEntry2->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
 838		if (type == LST_INTEGER)
 839		{
 840			S32 offset = chunk->mCurrentOffset - 4;
 841			bytestream_int2float(chunk->mCodeChunk, offset);
 842		}
 843		mEntry1->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
 844		if (type == LST_INTEGER)
 845		{
 846			S32 offset = chunk->mCurrentOffset - 4;
 847			bytestream_int2float(chunk->mCodeChunk, offset);
 848		}
 849		if (mNextp)
 850		{
 851			mNextp->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
 852		}
 853		break;
 854	case LSCP_LIST_BUILD_SIMPLE:
 855		{
 856			LLScriptByteCodeChunk	*list = new LLScriptByteCodeChunk(FALSE);
 857			mEntry3->recurse(fp, tabs, tabsize, LSCP_EMIT_BYTE_CODE, ptype, prunearg, scope, type, basetype, count, list, heap, stacksize, entry, entrycount, NULL);
 858			if (type == LST_INTEGER)
 859			{
 860				S32 offset = list->mCurrentOffset - 4;
 861				bytestream_int2float(list->mCodeChunk, offset);
 862			}
 863			mEntry2->recurse(fp, tabs, tabsize, LSCP_EMIT_BYTE_CODE, ptype, prunearg, scope, type, basetype, count, list, heap, stacksize, entry, entrycount, NULL);
 864			if (type == LST_INTEGER)
 865			{
 866				S32 offset = list->mCurrentOffset - 4;
 867				bytestream_int2float(list->mCodeChunk, offset);
 868			}
 869			mEntry1->recurse(fp, tabs, tabsize, LSCP_EMIT_BYTE_CODE, ptype, prunearg, scope, type, basetype, count, list, heap, stacksize, entry, entrycount, NULL);
 870			if (type == LST_INTEGER)
 871			{
 872				S32 offset = list->mCurrentOffset - 4;
 873				bytestream_int2float(list->mCodeChunk, offset);
 874			}
 875			LLVector3 vec;
 876			S32 offset = 0;
 877			bytestream2vector(vec, list->mCodeChunk, offset);
 878			*ldata = new LLScriptLibData(vec);
 879			delete list;
 880			if (mNextp)
 881			{
 882				mNextp->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, &(*ldata)->mListp);
 883			}
 884		}
 885		break;
 886	case LSCP_EMIT_CIL_ASSEMBLY:
 887
 888		// Load arguments.
 889		mEntry1->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
 890		if(LST_INTEGER == get_type(mEntry1))
 891		{
 892			print_cil_cast(fp, LST_INTEGER, LST_FLOATINGPOINT);
 893		}
 894		mEntry2->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
 895		if(LST_INTEGER == get_type(mEntry2))
 896		{
 897			print_cil_cast(fp, LST_INTEGER, LST_FLOATINGPOINT);
 898		}
 899		mEntry3->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
 900		if(LST_INTEGER == get_type(mEntry3))
 901		{
 902			print_cil_cast(fp, LST_INTEGER, LST_FLOATINGPOINT);
 903		}
 904		
 905		// Call named ctor, which leaves new Vector on stack, so it can be saved in to local or argument just like a primitive type.
 906		fprintf(fp, "call class [ScriptTypes]LindenLab.SecondLife.Vector class [LslUserScript]LindenLab.SecondLife.LslUserScript::'CreateVector'(float32, float32, float32)\n");
 907
 908		// Next.
 909		if (mNextp)
 910		{
 911			mNextp->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
 912		}
 913		break;
 914	default:
 915		mEntry3->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
 916		mEntry2->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
 917		mEntry1->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
 918		if (mNextp)
 919		{
 920			mNextp->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
 921		}
 922		break;
 923	}
 924}
 925
 926S32 LLScriptSAVector::getSize()
 927{
 928	return mEntry1->getSize() + mEntry2->getSize() + mEntry3->getSize();
 929}
 930
 931void LLScriptSAQuaternion::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCompilePass pass, LSCRIPTPruneType ptype, BOOL &prunearg, LLScriptScope *scope, LSCRIPTType &type, LSCRIPTType basetype, U64 &count, LLScriptByteCodeChunk *chunk, LLScriptByteCodeChunk *heap, S32 stacksize, LLScriptScopeEntry *entry, S32 entrycount, LLScriptLibData **ldata)
 932{
 933	if (gErrorToText.getErrors())
 934	{
 935		return;
 936	}
 937	switch(pass)
 938	{
 939	case LSCP_PRETTY_PRINT:
 940	case LSCP_EMIT_ASSEMBLY:
 941		fprintf(fp, "< ");
 942		mEntry4->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
 943		fprintf(fp, ", ");
 944		mEntry3->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
 945		fprintf(fp, ", ");
 946		mEntry2->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
 947		fprintf(fp, ", ");
 948		mEntry1->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
 949		fprintf(fp, " >");
 950		if (mNextp)
 951		{
 952			fprintf(fp, ", ");
 953			mNextp->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
 954		}
 955		break;
 956	case LSCP_TYPE:
 957		// vector's take floats
 958		mEntry4->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
 959		if (!legal_assignment(LST_FLOATINGPOINT, type))
 960		{
 961			gErrorToText.writeError(fp, this, LSERROR_TYPE_MISMATCH);
 962		}
 963		mEntry3->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
 964		if (!legal_assignment(LST_FLOATINGPOINT, type))
 965		{
 966			gErrorToText.writeError(fp, this, LSERROR_TYPE_MISMATCH);
 967		}
 968		mEntry2->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
 969		if (!legal_assignment(LST_FLOATINGPOINT, type))
 970		{
 971			gErrorToText.writeError(fp, this, LSERROR_TYPE_MISMATCH);
 972		}
 973		mEntry1->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
 974		if (!legal_assignment(LST_FLOATINGPOINT, type))
 975		{
 976			gErrorToText.writeError(fp, this, LSERROR_TYPE_MISMATCH);
 977		}
 978		type = LST_QUATERNION;
 979		if (mNextp)
 980		{
 981			mNextp->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
 982		}
 983		break;
 984	case LSCP_EMIT_BYTE_CODE:
 985		mEntry4->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
 986		if (type == LST_INTEGER)
 987		{
 988			S32 offset = chunk->mCurrentOffset - 4;
 989			bytestream_int2float(chunk->mCodeChunk, offset);
 990		}
 991		mEntry3->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
 992		if (type == LST_INTEGER)
 993		{
 994			S32 offset = chunk->mCurrentOffset - 4;
 995			bytestream_int2float(chunk->mCodeChunk, offset);
 996		}
 997		mEntry2->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
 998		if (type == LST_INTEGER)
 999		{
1000			S32 offset = chunk->mCurrentOffset - 4;
1001			bytestream_int2float(chunk->mCodeChunk, offset);
1002		}
1003		mEntry1->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
1004		if (type == LST_INTEGER)
1005		{
1006			S32 offset = chunk->mCurrentOffset - 4;
1007			bytestream_int2float(chunk->mCodeChunk, offset);
1008		}
1009		if (mNextp)
1010		{
1011			mNextp->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
1012		}
1013		break;
1014	case LSCP_LIST_BUILD_SIMPLE:
1015		{
1016			LLScriptByteCodeChunk	*list = new LLScriptByteCodeChunk(FALSE);
1017			mEntry4->recurse(fp, tabs, tabsize, LSCP_EMIT_BYTE_CODE, ptype, prunearg, scope, type, basetype, count, list, heap, stacksize, entry, entrycount, NULL);
1018			if (type == LST_INTEGER)
1019			{
1020				S32 offset = list->mCurrentOffset - 4;
1021				bytestream_int2float(list->mCodeChunk, offset);
1022			}
1023			mEntry3->recurse(fp, tabs, tabsize, LSCP_EMIT_BYTE_CODE, ptype, prunearg, scope, type, basetype, count, list, heap, stacksize, entry, entrycount, NULL);
1024			if (type == LST_INTEGER)
1025			{
1026				S32 offset = list->mCurrentOffset - 4;
1027				bytestream_int2float(list->mCodeChunk, offset);
1028			}
1029			mEntry2->recurse(fp, tabs, tabsize, LSCP_EMIT_BYTE_CODE, ptype, prunearg, scope, type, basetype, count, list, heap, stacksize, entry, entrycount, NULL);
1030			if (type == LST_INTEGER)
1031			{
1032				S32 offset = list->mCurrentOffset - 4;
1033				bytestream_int2float(list->mCodeChunk, offset);
1034			}
1035			mEntry1->recurse(fp, tabs, tabsize, LSCP_EMIT_BYTE_CODE, ptype, prunearg, scope, type, basetype, count, list, heap, stacksize, entry, entrycount, NULL);
1036			if (type == LST_INTEGER)
1037			{
1038				S32 offset = list->mCurrentOffset - 4;
1039				bytestream_int2float(list->mCodeChunk, offset);
1040			}
1041			LLQuaternion quat;
1042			S32 offset = 0;
1043			bytestream2quaternion(quat, list->mCodeChunk, offset);
1044			*ldata = new LLScriptLibData(quat);
1045			delete list;
1046			if (mNextp)
1047			{
1048				mNextp->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, &(*ldata)->mListp);
1049			}
1050		}
1051		break;
1052	case LSCP_EMIT_CIL_ASSEMBLY:
1053
1054		// Load arguments.
1055		mEntry1->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
1056		if(LST_INTEGER == get_type(mEntry1))
1057		{
1058			print_cil_cast(fp, LST_INTEGER, LST_FLOATINGPOINT);
1059		}
1060		mEntry2->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
1061		if(LST_INTEGER == get_type(mEntry2))
1062		{
1063			print_cil_cast(fp, LST_INTEGER, LST_FLOATINGPOINT);
1064		}
1065		mEntry3->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
1066		if(LST_INTEGER == get_type(mEntry3))
1067		{
1068			print_cil_cast(fp, LST_INTEGER, LST_FLOATINGPOINT);
1069		}
1070		mEntry4->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
1071		if(LST_INTEGER == get_type(mEntry4))
1072		{
1073			print_cil_cast(fp, LST_INTEGER, LST_FLOATINGPOINT);
1074		}
1075		
1076		// Call named ctor, which leaves new Vector on stack, so it can be saved in to local or argument just like a primitive type.
1077		fprintf(fp, "call class [ScriptTypes]LindenLab.SecondLife.Quaternion class [LslUserScript]LindenLab.SecondLife.LslUserScript::'CreateQuaternion'(float32, float32, float32, float32)\n");
1078
1079		// Next.
1080		if (mNextp)
1081		{
1082			mNextp->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
1083		}
1084		break;
1085	default:
1086		mEntry4->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
1087		mEntry3->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
1088		mEntry2->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
1089		mEntry1->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
1090		if (mNextp)
1091		{
1092			mNextp->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
1093		}
1094		break;
1095	}
1096}
1097
1098S32 LLScriptSAQuaternion::getSize()
1099{
1100	return mEntry1->getSize() + mEntry2->getSize() + mEntry3->getSize() + mEntry4->getSize();
1101}
1102
1103void LLScriptSAList::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCompilePass pass, LSCRIPTPruneType ptype, BOOL &prunearg, LLScriptScope *scope, LSCRIPTType &type, LSCRIPTType basetype, U64 &count, LLScriptByteCodeChunk *chunk, LLScriptByteCodeChunk *heap, S32 stacksize, LLScriptScopeEntry *entry, S32 entrycount, LLScriptLibData **ldata)
1104{
1105	if (gErrorToText.getErrors())
1106	{
1107		return;
1108	}
1109	switch(pass)
1110	{
1111	case LSCP_PRETTY_PRINT:
1112	case LSCP_EMIT_ASSEMBLY:
1113		fprintf(fp, "[ ");
1114		if (mEntryList)
1115			mEntryList->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
1116		fprintf(fp, " ]");
1117		if (mNextp)
1118		{
1119			fprintf(fp, ", ");
1120			mNextp->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
1121		}
1122		break;
1123	case LSCP_TYPE:
1124		if (mEntryList)
1125			mEntryList->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
1126		type = LST_LIST;
1127		if (mNextp)
1128		{
1129			mNextp->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
1130		}
1131		break;
1132	case LSCP_EMIT_BYTE_CODE:
1133		{
1134			LLScriptLibData *list_data = new LLScriptLibData;
1135
1136			list_data->mType = LST_LIST;
1137			if (mEntryList)
1138				mEntryList->recurse(fp, tabs, tabsize, LSCP_LIST_BUILD_SIMPLE, ptype, prunearg, scope, type, basetype, count, chunk, NULL, stacksize, entry, entrycount, &(list_data->mListp));
1139
1140			U8 *temp;
1141			chunk->addInteger(heap->mCurrentOffset + 1);
1142			S32 size = lsa_create_data_block(&temp, list_data, heap->mCurrentOffset);
1143			heap->addBytes(temp, size);
1144			delete list_data;
1145			delete [] temp;
1146
1147			if (mNextp)
1148			{
1149				mNextp->recurse(fp, tabs, tabsize, LSCP_EMIT_BYTE_CODE, ptype, prunearg, scope, type, basetype, count, chunk, NULL, stacksize, entry, entrycount, NULL);
1150			}
1151		}
1152		break;
1153	case LSCP_EMIT_CIL_ASSEMBLY:
1154		{
1155			// Create list.
1156			fprintf(fp, "call class [mscorlib]System.Collections.ArrayList [LslUserScript]LindenLab.SecondLife.LslUserScript::CreateList()\n");
1157
1158			// Add elements.
1159			LLScriptSimpleAssignable* current_entry = mEntryList;
1160			LLScriptSimpleAssignable* next_entry = NULL;
1161			while(NULL != current_entry)
1162			{
1163				next_entry = current_entry->mNextp;
1164
1165				// Null mNextp pointer, so only current list element is processed.
1166				current_entry->mNextp = NULL;
1167				current_entry->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
1168
1169				// Restore mNextp pointer.
1170				current_entry->mNextp = next_entry;
1171
1172				// Box element and store in list.
1173				print_cil_box(fp, get_type(current_entry));
1174				fprintf(fp, "call class [mscorlib]System.Collections.ArrayList class [LslUserScript]LindenLab.SecondLife.LslUserScript::Append(class [mscorlib]System.Collections.ArrayList, object)\n");
1175
1176				// Process next element.
1177				current_entry = next_entry;
1178			}
1179
1180			// Process next list.
1181			if (mNextp)
1182			{
1183				mNextp->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
1184			}
1185		}
1186		break;
1187	default:
1188		if (mEntryList)
1189			mEntryList->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, ldata);
1190		if (mNextp)
1191		{
1192			mNextp->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, ldata);
1193		}
1194		break;
1195	}
1196}
1197
1198S32 LLScriptSAList::getSize()
1199{
1200	return mEntryList->getSize();
1201}
1202
1203void LLScriptGlobalVariable::addGlobal(LLScriptGlobalVariable *global)
1204{
1205	if (mNextp)
1206	{
1207		global->mNextp = mNextp;
1208	}
1209	mNextp = global;
1210}
1211
1212void LLScriptGlobalVariable::gonext(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCompilePass pass, LSCRIPTPruneType ptype, BOOL &prunearg, LLScriptScope *scope, LSCRIPTType &type, LSCRIPTType basetype, U64 &count, LLScriptByteCodeChunk *chunk, LLScriptByteCodeChunk *heap, S32 stacksize, LLScriptScopeEntry *entry, S32 entrycount, LLScriptLibData **ldata)
1213{
1214	switch(pass)
1215	{
1216	case LSCP_PRETTY_PRINT:
1217		if (mNextp)
1218		{
1219			mNextp->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
1220		}
1221		break;
1222	default:
1223		if (mNextp)
1224		{
1225			mNextp->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
1226		}
1227		break;
1228	}
1229}
1230
1231// Push initialised variable of type on to stack.
1232static void print_cil_init_variable(LLFILE* fp, LSCRIPTType type)
1233{
1234	switch(type)
1235	{
1236	case LST_INTEGER:
1237		fprintf(fp, "ldc.i4.0\n");
1238		break;
1239	case LST_FLOATINGPOINT:
1240		fprintf(fp, "ldc.r8 0\n");
1241		break;
1242	case LST_STRING:
1243		fprintf(fp, "ldstr \"\"\n");
1244		break;
1245	case LST_KEY:
1246		fprintf(fp, "ldstr \"\"\n");
1247		fprintf(fp, "call valuetype [ScriptTypes]LindenLab.SecondLife.Key class [LslUserScript]LindenLab.SecondLife.LslUserScript::'CreateKey'(string)\n");
1248		break;
1249	case LST_VECTOR:
1250		fprintf(fp, "ldc.r8 0\n");
1251		fprintf(fp, "ldc.r8 0\n");
1252		fprintf(fp, "ldc.r8 0\n");
1253		fprintf(fp, "call class [ScriptTypes]LindenLab.SecondLife.Vector class [LslUserScript]LindenLab.SecondLife.LslUserScript::'CreateVector'(float32, float32, float32)\n");
1254		break;
1255	case LST_QUATERNION:
1256		fprintf(fp, "ldc.r8 0\n");
1257		fprintf(fp, "ldc.r8 0\n");
1258		fprintf(fp, "ldc.r8 0\n");
1259		fprintf(fp, "ldc.r8 1\n");
1260		fprintf(fp, "call class [ScriptTypes]LindenLab.SecondLife.Quaternion class [LslUserScript]LindenLab.SecondLife.LslUserScript::'CreateQuaternion'(float32, float32, float32, float32)\n");
1261		break;
1262	case LST_LIST:
1263		fprintf(fp, "call class [mscorlib]System.Collections.ArrayList class [LslUserScript]LindenLab.SecondLife.LslUserScript::CreateList()\n");
1264		break;
1265	default:
1266		break;
1267	}
1268}
1269
1270void LLScriptGlobalVariable::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCompilePass pass, LSCRIPTPruneType ptype, BOOL &prunearg, LLScriptScope *scope, LSCRIPTType &type, LSCRIPTType basetype, U64 &count, LLScriptByteCodeChunk *chunk, LLScriptByteCodeChunk *heap, S32 stacksize, LLScriptScopeEntry *entry, S32 entrycount, LLScriptLibData **ldata)
1271{
1272	if (gErrorToText.getErrors())
1273	{
1274		return;
1275	}
1276	switch(pass)
1277	{
1278	case LSCP_PRETTY_PRINT:
1279		mType->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
1280		fprintf(fp,"\t");
1281		mIdentifier->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
1282		if (mAssignable)
1283		{
1284			fprintf(fp, " = ");
1285			mAssignable->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
1286		}
1287		fprintf(fp, ";\n");
1288		break;
1289	case LSCP_EMIT_ASSEMBLY:
1290		mType->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
1291		fprintf(fp,"\t");
1292		mIdentifier->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
1293		if (mAssignable)
1294		{
1295			fprintf(fp, " = ");
1296			mAssignable->recurse(fp, tabs, tabsize, LSCP_PRETTY_PRINT, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
1297			fprintf(fp, "\n");
1298			fprintf(fp, "Offset: %d Type: %d\n", mIdentifier->mScopeEntry->mOffset, (S32)LSCRIPTTypeByte[mType->mType]);
1299		}
1300		else
1301		{
1302			fprintf(fp, "\n");
1303			fprintf(fp, "Offset: %d Type: %d\n", mIdentifier->mScopeEntry->mOffset, (S32)LSCRIPTTypeByte[mType->mType]);
1304		}
1305		break;
1306	case LSCP_SCOPE_PASS1:
1307		if (scope->checkEntry(mIdentifier->mName))
1308		{
1309			gErrorToText.writeError(fp, this, LSERROR_DUPLICATE_NAME);
1310		}
1311		else
1312		{
1313			if (mAssignable)
1314			{
1315				mAssignable->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
1316			}			
1317			// this needs to go after expression decent to make sure that we don't add ourselves or something silly
1318			mIdentifier->mScopeEntry = scope->addEntry(mIdentifier->mName, LIT_GLOBAL, mType->mType);
1319			if (mIdentifier->mScopeEntry && mAssignable)
1320					mIdentifier->mScopeEntry->mAssignable = mAssignable;
1321		}
1322		break;
1323	case LSCP_TYPE:
1324		// if the variable has an assignable, it must assignable to the variable's type
1325		if (mAssignable)
1326		{
1327			mAssignable->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
1328			mAssignableType = type;
1329			if (!legal_assignment(mType->mType, mAssignableType))
1330			{
1331				gErrorToText.writeError(fp, this, LSERROR_TYPE_MISMATCH);
1332			}
1333		}
1334		break;
1335	case LSCP_RESOURCE:
1336		{
1337			// we're just tryng to determine how much space the variable needs
1338			// it also includes the name of the variable as well as the type
1339			// plus 4 bytes of offset from it's apparent address to the actual data
1340#ifdef LSL_INCLUDE_DEBUG_INFO
1341			count += strlen(mIdentifier->mName) + 1 + 1 + 4;
1342#else
1343			count += 1 + 1 + 4;
1344#endif
1345			mIdentifier->mScopeEntry->mOffset = (S32)count;
1346			mIdentifier->mScopeEntry->mSize = mType->getSize();
1347			count += mIdentifier->mScopeEntry->mSize;
1348			mIdentifier->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
1349		}
1350		break;
1351	case LSCP_EMIT_BYTE_CODE:
1352		{
1353			// order for global variables
1354			// 0 - 4: offset to actual data
1355			S32 offsetoffset = chunk->mCurrentOffset;
1356			S32 offsetdelta = 0;
1357			chunk->addBytes(4);
1358			// type
1359			char vtype;
1360			vtype = LSCRIPTTypeByte[mType->mType]; 
1361			chunk->addBytes(&vtype, 1);
1362			// null terminated name
1363#ifdef LSL_INCLUDE_DEBUG_INFO
1364			chunk->addBytes(mIdentifier->mName, strlen(mIdentifier->mName) + 1);
1365#else
1366			chunk->addBytes(1);
1367#endif
1368			// put correct offset delta in
1369			offsetdelta = chunk->mCurrentOffset - offsetoffset;
1370			integer2bytestream(chunk->mCodeChunk, offsetoffset, offsetdelta);
1371
1372			// now we need space for the variable itself
1373			LLScriptByteCodeChunk	*value = new LLScriptByteCodeChunk(FALSE);
1374			if (mAssignable)
1375			{
1376				mAssignable->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, value, heap, stacksize, entry, entrycount, NULL);
1377				// need to put sneaky type conversion here
1378				if (mAssignableType != mType->mType)
1379				{
1380					// the only legal case that is a problem is int->float
1381					if (mType->mType == LST_FLOATINGPOINT && mAssignableType == LST_INTEGER)
1382					{
1383						S32 offset = value->mCurrentOffset - 4;
1384						bytestream_int2float(value->mCodeChunk, offset);
1385					}
1386				}
1387			}
1388			else
1389			{
1390				if (  (mType->mType == LST_STRING)
1391					||(mType->mType == LST_KEY))
1392				{
1393					// string and keys (even empty ones) need heap entries
1394					chunk->addInteger(heap->mCurrentOffset + 1);
1395					LLScriptLibData *data = new LLScriptLibData("");
1396					U8 *temp;
1397					S32 size = lsa_create_data_block(&temp, data, heap->mCurrentOffset);
1398
1399					heap->addBytes(temp, size);
1400					delete [] temp;
1401					delete data;
1402				}
1403				else if (mType->mType == LST_LIST)
1404				{
1405					chunk->addInteger(heap->mCurrentOffset + 1);
1406					LLScriptLibData *data = new LLScriptLibData;
1407					data->mType = LST_LIST;
1408					U8 *temp;
1409					S32 size = lsa_create_data_block(&temp, data, heap->mCurrentOffset);
1410
1411					heap->addBytes(temp, size);
1412					delete [] temp;
1413					delete data;
1414				}
1415				else if (mType->mType == LST_QUATERNION)
1416				{
1417					chunk->addFloat(1.f);
1418					chunk->addFloat(0.f);
1419					chunk->addFloat(0.f);
1420					chunk->addFloat(0.f);
1421				}
1422				else
1423				{
1424					value->addBytes(LSCRIPTDataSize[mType->mType]);
1425				}
1426			}
1427			chunk->addBytes(value->mCodeChunk, value->mCurrentOffset);
1428			delete value;
1429		}
1430		break;
1431	case LSCP_EMIT_CIL_ASSEMBLY:
1432
1433		// Initialisation inside ctor.
1434		fprintf(fp, "ldarg.0\n");
1435		if (mAssignable)
1436		{
1437			// Initialise to value.
1438			mAssignable->recurse(fp, tabs, tabsize, LSCP_EMIT_CIL_ASSEMBLY,
1439								 ptype, prunearg, scope, type, basetype,
1440								 count, chunk, heap, stacksize, entry,
1441								 entrycount, NULL);
1442			print_cil_assignment_cast(fp, get_type(mAssignable), mType->mType);
1443		}
1444		else
1445		{
1446			// Initialise to zero.
1447			print_cil_init_variable(fp, mType->mType);
1448		}
1449		// Store value.
1450		fprintf(fp, "stfld ");
1451		mType->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
1452		fprintf(fp," %s::", gScriptp->getClassName());
1453		mIdentifier->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
1454		fprintf(fp, "\n");
1455		break;
1456	default:
1457		mType->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
1458		mIdentifier->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
1459		if (mAssignable)
1460		{
1461			mAssignable->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
1462		}
1463		break;
1464	}
1465	gonext(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
1466}
1467
1468S32 LLScriptGlobalVariable::getSize()
1469{
1470	S32 return_size;
1471
1472	return_size = mType->getSize();
1473	return return_size;
1474}
1475
1476void LLScriptEvent::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCompilePass pass, LSCRIPTPruneType ptype, BOOL &prunearg, LLScriptScope *scope, LSCRIPTType &type, LSCRIPTType basetype, U64 &count, LLScriptByteCodeChunk *chunk, LLScriptByteCodeChunk *heap, S32 stacksize, LLScriptScopeEntry *entry, S32 entrycount, LLScriptLibData **ldata)
1477{
1478	fprintf(fp, "Event Base Class -- should never get here!\n");
1479}
1480
1481S32 LLScriptEvent::getSize()
1482{
1483	printf("Event Base Class -- should never get here!\n");
1484	return 0;
1485}
1486static void checkForDuplicateHandler(LLFILE *fp, LLScriptFilePosition *pos, 
1487				     LLScriptScope *scope,
1488				     const char* name)
1489{
1490    LLScriptScope *parent = scope->mParentScope;
1491    if (parent->

Large files files are truncated, but you can click here to view the full file