summaryrefslogtreecommitdiff
path: root/indra/lscript/lscript_compile/lscript_tree.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'indra/lscript/lscript_compile/lscript_tree.cpp')
-rw-r--r--indra/lscript/lscript_compile/lscript_tree.cpp9998
1 files changed, 9998 insertions, 0 deletions
diff --git a/indra/lscript/lscript_compile/lscript_tree.cpp b/indra/lscript/lscript_compile/lscript_tree.cpp
new file mode 100644
index 0000000000..4b4a7f13f4
--- /dev/null
+++ b/indra/lscript/lscript_compile/lscript_tree.cpp
@@ -0,0 +1,9998 @@
+/**
+ * @file lscript_tree.cpp
+ * @brief implements methods for lscript_tree.h classes
+ *
+ * Copyright (c) 2002-$CurrentYear$, Linden Research, Inc.
+ * $License$
+ */
+
+// TO DO: Move print functionality from .h file to here
+
+#include "linden_common.h"
+
+#include "lscript_tree.h"
+#include "lscript_typecheck.h"
+#include "lscript_resource.h"
+#include "lscript_bytecode.h"
+#include "lscript_heap.h"
+#include "lscript_library.h"
+#include "lscript_alloc.h"
+
+//#define LSL_INCLUDE_DEBUG_INFO
+
+void print_cil_box(FILE* fp, LSCRIPTType type)
+{
+ switch(type)
+ {
+ case LST_INTEGER:
+ fprintf(fp, "box [mscorlib]System.Int32\n");
+ break;
+ case LST_FLOATINGPOINT:
+ fprintf(fp, "box [mscorlib]System.Double\n");
+ break;
+ case LST_STRING:
+ case LST_KEY:
+ fprintf(fp, "box [mscorlib]System.String\n");
+ break;
+ case LST_VECTOR:
+ fprintf(fp, "box [LScriptLibrary]LLVector\n");
+ break;
+ case LST_QUATERNION:
+ fprintf(fp, "box [LScriptLibrary]LLQuaternion\n");
+ break;
+ default:
+ break;
+ }
+}
+
+void print_cil_type(FILE* fp, LSCRIPTType type)
+{
+ switch(type)
+ {
+ case LST_INTEGER:
+ fprintf(fp, "int32");
+ break;
+ case LST_FLOATINGPOINT:
+ fprintf(fp, "float32");
+ break;
+ case LST_STRING:
+ case LST_KEY:
+ fprintf(fp, "string");
+ break;
+ case LST_VECTOR:
+ fprintf(fp, "valuetype [LScriptLibrary]LLVector");
+ break;
+ case LST_QUATERNION:
+ fprintf(fp, "valuetype [LScriptLibrary]LLQuaternion");
+ break;
+ case LST_LIST:
+ fprintf(fp, "class [mscorlib]System.Collections.ArrayList");
+ break;
+ case LST_NULL:
+ fprintf(fp, "void");
+ break;
+ default:
+ break;
+ }
+}
+
+void LLScriptType::recurse(FILE *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)
+{
+ if (gErrorToText.getErrors())
+ {
+ return;
+ }
+ switch(pass)
+ {
+ case LSCP_PRETTY_PRINT:
+ case LSCP_EMIT_ASSEMBLY:
+ fprintf(fp,"%s",LSCRIPTTypeNames[mType]);
+ break;
+ case LSCP_TYPE:
+ type = mType;
+ break;
+ case LSCP_EMIT_CIL_ASSEMBLY:
+ print_cil_type(fp, mType);
+ break;
+ default:
+ break;
+ }
+}
+
+S32 LLScriptType::getSize()
+{
+ return LSCRIPTDataSize[mType];
+}
+
+void LLScriptConstant::recurse(FILE *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)
+{
+ if (gErrorToText.getErrors())
+ {
+ return;
+ }
+ switch(pass)
+ {
+ case LSCP_PRETTY_PRINT:
+ case LSCP_EMIT_ASSEMBLY:
+ fprintf(fp,"Script Constant Base class -- should never get here!\n");
+ break;
+ default:
+ break;
+ }
+}
+
+S32 LLScriptConstant::getSize()
+{
+ printf("Script Constant Base class -- should never get here!\n");
+ return 0;
+}
+
+
+
+void LLScriptConstantInteger::recurse(FILE *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)
+{
+ if (gErrorToText.getErrors())
+ {
+ return;
+ }
+ switch(pass)
+ {
+ case LSCP_PRETTY_PRINT:
+ fprintf(fp, "%d", mValue);
+ break;
+ case LSCP_EMIT_ASSEMBLY:
+ fprintf(fp, "PUSHARGI %d\n", mValue);
+ break;
+ case LSCP_TYPE:
+ type = mType;
+ break;
+ case LSCP_EMIT_BYTE_CODE:
+ {
+ chunk->addInteger(mValue);
+ type = mType;
+ }
+ break;
+ case LSCP_TO_STACK:
+ {
+ chunk->addByte(LSCRIPTOpCodes[LOPC_PUSHARGI]);
+ chunk->addInteger(mValue);
+ type = mType;
+ }
+ break;
+ case LSCP_LIST_BUILD_SIMPLE:
+ {
+ *ldata = new LLScriptLibData(mValue);
+ }
+ break;
+ case LSCP_EMIT_CIL_ASSEMBLY:
+ fprintf(fp, "ldc.i4 %d\n", mValue);
+ break;
+ default:
+ break;
+ }
+}
+
+S32 LLScriptConstantInteger::getSize()
+{
+ return LSCRIPTDataSize[LST_INTEGER];
+}
+
+void LLScriptConstantFloat::recurse(FILE *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)
+{
+ if (gErrorToText.getErrors())
+ {
+ return;
+ }
+ switch(pass)
+ {
+ case LSCP_PRETTY_PRINT:
+ fprintf(fp, "%5.5f", mValue);
+ break;
+ case LSCP_EMIT_ASSEMBLY:
+ fprintf(fp, "PUSHARGF %5.5f\n", mValue);
+ break;
+ case LSCP_TYPE:
+ type = mType;
+ break;
+ case LSCP_EMIT_BYTE_CODE:
+ {
+ chunk->addFloat(mValue);
+ type = mType;
+ }
+ break;
+ case LSCP_TO_STACK:
+ {
+ chunk->addByte(LSCRIPTOpCodes[LOPC_PUSHARGF]);
+ chunk->addFloat(mValue);
+ type = mType;
+ }
+ break;
+ case LSCP_LIST_BUILD_SIMPLE:
+ {
+ *ldata = new LLScriptLibData(mValue);
+ }
+ break;
+ case LSCP_EMIT_CIL_ASSEMBLY:
+ fprintf(fp, "ldc.r8 %5.5f\n", mValue); // NOTE: Precision?
+ default:
+ break;
+ }
+}
+
+S32 LLScriptConstantFloat::getSize()
+{
+ return LSCRIPTDataSize[LST_FLOATINGPOINT];
+}
+
+void print_escape_quotes(FILE* fp, const char* str)
+{
+ putc('"', fp);
+ for(const char* c = str; *c != '\0'; ++c)
+ {
+ if(*c == '"')
+ {
+ putc('\\', fp);
+ }
+ putc(*c, fp);
+ }
+ putc('"', fp);
+}
+
+void LLScriptConstantString::recurse(FILE *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)
+{
+ if (gErrorToText.getErrors())
+ {
+ return;
+ }
+ switch(pass)
+ {
+ case LSCP_PRETTY_PRINT:
+ fprintf(fp, "\"%s\"", mValue);
+ break;
+ case LSCP_EMIT_ASSEMBLY:
+ fprintf(fp, "PUSHARGS \"%s\"\n", mValue);
+ fprintf(fp, "STACKTOS %lu\n", strlen(mValue) + 1);
+ break;
+ case LSCP_TYPE:
+ type = mType;
+ break;
+ case LSCP_EMIT_BYTE_CODE:
+ {
+ chunk->addInteger(heap->mCurrentOffset + 1);
+ LLScriptLibData *data = new LLScriptLibData(mValue);
+ U8 *temp;
+ S32 size = lsa_create_data_block(&temp, data, heap->mCurrentOffset);
+
+ heap->addBytes(temp, size);
+ delete [] temp;
+ delete data;
+ }
+ break;
+ case LSCP_TO_STACK:
+ {
+ chunk->addByte(LSCRIPTOpCodes[LOPC_PUSHARGS]);
+ chunk->addBytes(mValue, (S32)strlen(mValue) + 1);
+ type = mType;
+ }
+ break;
+ case LSCP_LIST_BUILD_SIMPLE:
+ {
+ *ldata = new LLScriptLibData(mValue);
+ }
+ break;
+ case LSCP_EMIT_CIL_ASSEMBLY:
+ fprintf(fp, "ldstr ");
+ print_escape_quotes(fp, mValue);
+ fprintf(fp, "\n");
+ default:
+ break;
+ }
+}
+
+S32 LLScriptConstantString::getSize()
+{
+ return (S32)strlen(mValue) + 1;
+}
+
+
+void LLScriptIdentifier::recurse(FILE *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)
+{
+ if (gErrorToText.getErrors())
+ {
+ return;
+ }
+ switch(pass)
+ {
+ case LSCP_PRETTY_PRINT:
+ fprintf(fp, "%s", mName);
+ break;
+ case LSCP_EMIT_ASSEMBLY:
+ if (mScopeEntry)
+ {
+ if (mScopeEntry->mIDType == LIT_VARIABLE)
+ {
+ fprintf(fp, "$BP + %d [%s]", mScopeEntry->mOffset, mName);
+ }
+ else if (mScopeEntry->mIDType == LIT_GLOBAL)
+ {
+ fprintf(fp, "$GVR + %d [%s]", mScopeEntry->mOffset, mName);
+ }
+ else
+ {
+ fprintf(fp, "%s", mName);
+ }
+ }
+ break;
+ case LSCP_TYPE:
+ if (mScopeEntry)
+ type = mScopeEntry->mType;
+ else
+ type = LST_NULL;
+ break;
+ case LSCP_RESOURCE:
+ if (mScopeEntry)
+ {
+ if (mScopeEntry->mIDType == LIT_VARIABLE)
+ {
+// fprintf(fp, "LOCAL : %d : %d : %s\n", mScopeEntry->mOffset, mScopeEntry->mSize, mName);
+ }
+ else if (mScopeEntry->mIDType == LIT_GLOBAL)
+ {
+// fprintf(fp, "GLOBAL: %d : %d : %s\n", mScopeEntry->mOffset, mScopeEntry->mSize, mName);
+ }
+ }
+ break;
+ case LSCP_LIST_BUILD_SIMPLE:
+ {
+ if (mScopeEntry)
+ {
+ if (mScopeEntry->mType == LST_LIST)
+ {
+ gErrorToText.writeError(fp, this, LSERROR_NO_LISTS_IN_LISTS);
+ }
+ else if (mScopeEntry->mAssignable)
+ {
+ mScopeEntry->mAssignable->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, ldata);
+ }
+ else
+ {
+ gErrorToText.writeError(fp, this, LSERROR_NO_UNITIALIZED_VARIABLES_IN_LISTS);
+ }
+ }
+ else
+ {
+ gErrorToText.writeError(fp, this, LSERROR_UNDEFINED_NAME);
+ }
+ }
+ break;
+ case LSCP_EMIT_CIL_ASSEMBLY:
+ fprintf(fp, "%s", mName);
+ break;
+ default:
+ break;
+ }
+}
+
+S32 LLScriptIdentifier::getSize()
+{
+
+ return 0;
+}
+
+
+
+void LLScriptSimpleAssignable::addAssignable(LLScriptSimpleAssignable *assign)
+{
+ if (mNextp)
+ {
+ assign->mNextp = mNextp;
+ }
+ mNextp = assign;
+}
+
+void LLScriptSimpleAssignable::recurse(FILE *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)
+{
+ if (gErrorToText.getErrors())
+ {
+ return;
+ }
+ fprintf(fp, "Simple Assignable Base Class -- should never get here!\n");
+}
+
+S32 LLScriptSimpleAssignable::getSize()
+{
+
+ printf("Simple Assignable Base Class -- should never get here!\n");
+ return 0;
+}
+
+void LLScriptSAIdentifier::recurse(FILE *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)
+{
+ if (gErrorToText.getErrors())
+ {
+ return;
+ }
+ switch(pass)
+ {
+ case LSCP_PRETTY_PRINT:
+ case LSCP_EMIT_ASSEMBLY:
+ mIdentifier->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ if (mNextp)
+ {
+ fprintf(fp, ", ");
+ mNextp->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ }
+ break;
+ case LSCP_SCOPE_PASS1:
+ {
+ LLScriptScopeEntry *entry = scope->findEntry(mIdentifier->mName);
+ if (!entry)
+ {
+ gErrorToText.writeError(fp, this, LSERROR_UNDEFINED_NAME);
+ }
+ else
+ {
+ // if we did find it, make sure this identifier is associated with the correct scope entry
+ mIdentifier->mScopeEntry = entry;
+ }
+ if (mNextp)
+ {
+ mNextp->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ }
+ }
+ break;
+ case LSCP_EMIT_BYTE_CODE:
+ {
+ if (mIdentifier->mScopeEntry)
+ {
+ if(mIdentifier->mScopeEntry->mAssignable)
+ {
+ mIdentifier->mScopeEntry->mAssignable->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ }
+ else
+ {
+ // Babbage: 29/8/06: If the scope entry has no mAssignable,
+ // set the default type and add the default 0 value to the
+ // chunk. Without this SAVectors and SAQuaternions will
+ // assume the arbitrary current type is the assignable type
+ // and may attempt to access a null chunk. (SL-20156)
+ type = mIdentifier->mScopeEntry->mType;
+ chunk->addBytes(LSCRIPTDataSize[type]);
+ }
+ }
+ if (mNextp)
+ {
+ mNextp->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ }
+ }
+ break;
+ case LSCP_LIST_BUILD_SIMPLE:
+ {
+ mIdentifier->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, ldata);
+ if (mNextp)
+ {
+ mNextp->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, &(*ldata)->mListp);
+ }
+ }
+ break;
+ default:
+ mIdentifier->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ if (mNextp)
+ {
+ mNextp->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ }
+ break;
+ }
+}
+
+S32 LLScriptSAIdentifier::getSize()
+{
+ return mIdentifier->getSize();
+}
+
+void LLScriptSAConstant::recurse(FILE *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)
+{
+ if (gErrorToText.getErrors())
+ {
+ return;
+ }
+ switch(pass)
+ {
+ case LSCP_PRETTY_PRINT:
+ case LSCP_EMIT_ASSEMBLY:
+ mConstant->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ if (mNextp)
+ {
+ fprintf(fp, ", ");
+ mNextp->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ }
+ break;
+ case LSCP_LIST_BUILD_SIMPLE:
+ {
+ mConstant->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, ldata);
+ if (mNextp)
+ {
+ mNextp->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, &(*ldata)->mListp);
+ }
+ }
+ break;
+ default:
+ mConstant->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ if (mNextp)
+ {
+ mNextp->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ }
+ break;
+ }
+}
+
+S32 LLScriptSAConstant::getSize()
+{
+ return mConstant->getSize();
+}
+
+void print_cil_cast(FILE* fp, LSCRIPTType srcType, LSCRIPTType targetType)
+{
+ switch(srcType)
+ {
+ case LST_INTEGER:
+ switch(targetType)
+ {
+ case LST_FLOATINGPOINT:
+ fprintf(fp, "conv.r8\n");
+ break;
+ case LST_STRING:
+ fprintf(fp, "call string class [mscorlib]System.Convert::ToString(int32)\n");
+ break;
+ case LST_LIST:
+ fprintf(fp, "box [mscorlib]System.Int32\n");
+ fprintf(fp, "call class [mscorlib]System.Collections.ArrayList class [LScriptLibrary]LScriptInternal::CreateList()\n");
+ fprintf(fp, "call class [mscorlib]System.Collections.ArrayList class [LScriptLibrary]LScriptInternal::AddReturnList(object, class [mscorlib]System.Collections.ArrayList)\n");
+ break;
+ default:
+ break;
+ }
+ break;
+ case LST_FLOATINGPOINT:
+ switch(targetType)
+ {
+ case LST_INTEGER:
+ fprintf(fp, "conv.i4\n");
+ break;
+ case LST_STRING:
+ fprintf(fp, "call string class [mscorlib]System.Convert::ToString(float32)\n");
+ break;
+ case LST_LIST:
+ fprintf(fp, "call class [mscorlib]System.Collections.ArrayList [LScriptLibrary]LScriptInternal::CreateList(object)\n");
+ break;
+ default:
+ break;
+ }
+ break;
+ case LST_STRING:
+ switch(targetType)
+ {
+ case LST_INTEGER:
+ fprintf(fp, "call int32 valuetype [mscorlib]System.Int32::Parse(string)\n");
+ break;
+ case LST_FLOATINGPOINT:
+ fprintf(fp, "call float64 valuetype [mscorlib]System.Double::Parse(string)\n");
+ break;
+ case LST_LIST:
+ fprintf(fp, "call class [mscorlib]System.Collections.ArrayList [LScriptLibrary]LScriptInternal::CreateList(object)\n");
+ break;
+ case LST_VECTOR:
+ fprintf(fp, "call valuetype [LScriptLibrary]LLVector valuetype [LScriptLibrary]LLVector::'Parse'(string)\n");
+ break;
+ case LST_QUATERNION:
+ fprintf(fp, "call valuetype [LScriptLibrary]LLQuaternion valuetype [LScriptLibrary]LLQuaternion::'Parse'(string)\n");
+ break;
+ default:
+ break;
+ }
+ break;
+ case LST_KEY:
+ switch(targetType)
+ {
+ case LST_KEY:
+ break;
+ case LST_STRING:
+ break;
+ case LST_LIST:
+ fprintf(fp, "call class [mscorlib]System.Collections.ArrayList [LScriptLibrary]LScriptInternal::CreateList(object)\n");
+ break;
+ default:
+ break;
+ }
+ break;
+ case LST_VECTOR:
+ switch(targetType)
+ {
+ case LST_VECTOR:
+ break;
+ case LST_STRING:
+ fprintf(fp, "call string valuetype [LScriptLibrary]LLVector::'ToString'(valuetype [LScriptLibrary]LLVector)\n");
+ break;
+ case LST_LIST:
+ fprintf(fp, "call class [mscorlib]System.Collections.ArrayList [LScriptLibrary]LScriptInternal::CreateList(object)\n");
+ break;
+ default:
+ break;
+ }
+ break;
+ case LST_QUATERNION:
+ switch(targetType)
+ {
+ case LST_QUATERNION:
+ break;
+ case LST_STRING:
+ fprintf(fp, "call string valuetype [LScriptLibrary]LLQuaternion::'ToString'(valuetype [LScriptLibrary]LLQuaternion)\n");
+ break;
+ case LST_LIST:
+ fprintf(fp, "call class [mscorlib]System.Collections.ArrayList [LScriptLibrary]LScriptInternal::CreateList(object)\n");
+ break;
+ default:
+ break;
+ }
+ break;
+ case LST_LIST:
+ switch(targetType)
+ {
+ case LST_LIST:
+ break;
+ case LST_STRING:
+ fprintf(fp, "call string [LScriptLibrary]LScriptInternal::ListToString(class [mscorlib]System.Collections.ArrayList)\n");
+ break;
+ default:
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+bool is_SA_constant_integer(LLScriptSimpleAssignable* sa)
+{
+ // HACK: Downcast based on type.
+ return (sa->mType == LSSAT_CONSTANT && ((LLScriptSAConstant*) sa)->mConstant->mType == LST_INTEGER);
+}
+
+void LLScriptSAVector::recurse(FILE *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)
+{
+ if (gErrorToText.getErrors())
+ {
+ return;
+ }
+ switch(pass)
+ {
+ case LSCP_PRETTY_PRINT:
+ case LSCP_EMIT_ASSEMBLY:
+ fprintf(fp, "< ");
+ mEntry3->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, ", ");
+ mEntry2->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, ", ");
+ mEntry1->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, " >");
+ if (mNextp)
+ {
+ fprintf(fp, ", ");
+ mNextp->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ }
+ break;
+ case LSCP_TYPE:
+ // vector's take floats
+ mEntry3->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ if (!legal_assignment(LST_FLOATINGPOINT, type))
+ {
+ gErrorToText.writeError(fp, this, LSERROR_TYPE_MISMATCH);
+ }
+ mEntry2->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ if (!legal_assignment(LST_FLOATINGPOINT, type))
+ {
+ gErrorToText.writeError(fp, this, LSERROR_TYPE_MISMATCH);
+ }
+ mEntry1->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ if (!legal_assignment(LST_FLOATINGPOINT, type))
+ {
+ gErrorToText.writeError(fp, this, LSERROR_TYPE_MISMATCH);
+ }
+ type = LST_VECTOR;
+ if (mNextp)
+ {
+ mNextp->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ }
+ break;
+ case LSCP_EMIT_BYTE_CODE:
+ mEntry3->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ if (type == LST_INTEGER)
+ {
+ S32 offset = chunk->mCurrentOffset - 4;
+ bytestream_int2float(chunk->mCodeChunk, offset);
+ }
+ mEntry2->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ if (type == LST_INTEGER)
+ {
+ S32 offset = chunk->mCurrentOffset - 4;
+ bytestream_int2float(chunk->mCodeChunk, offset);
+ }
+ mEntry1->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ if (type == LST_INTEGER)
+ {
+ S32 offset = chunk->mCurrentOffset - 4;
+ bytestream_int2float(chunk->mCodeChunk, offset);
+ }
+ if (mNextp)
+ {
+ mNextp->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ }
+ break;
+ case LSCP_LIST_BUILD_SIMPLE:
+ {
+ LLScriptByteCodeChunk *list = new LLScriptByteCodeChunk(FALSE);
+ mEntry3->recurse(fp, tabs, tabsize, LSCP_EMIT_BYTE_CODE, ptype, prunearg, scope, type, basetype, count, list, heap, stacksize, entry, entrycount, NULL);
+ if (type == LST_INTEGER)
+ {
+ S32 offset = list->mCurrentOffset - 4;
+ bytestream_int2float(list->mCodeChunk, offset);
+ }
+ mEntry2->recurse(fp, tabs, tabsize, LSCP_EMIT_BYTE_CODE, ptype, prunearg, scope, type, basetype, count, list, heap, stacksize, entry, entrycount, NULL);
+ if (type == LST_INTEGER)
+ {
+ S32 offset = list->mCurrentOffset - 4;
+ bytestream_int2float(list->mCodeChunk, offset);
+ }
+ mEntry1->recurse(fp, tabs, tabsize, LSCP_EMIT_BYTE_CODE, ptype, prunearg, scope, type, basetype, count, list, heap, stacksize, entry, entrycount, NULL);
+ if (type == LST_INTEGER)
+ {
+ S32 offset = list->mCurrentOffset - 4;
+ bytestream_int2float(list->mCodeChunk, offset);
+ }
+ LLVector3 vec;
+ S32 offset = 0;
+ bytestream2vector(vec, list->mCodeChunk, offset);
+ *ldata = new LLScriptLibData(vec);
+ delete list;
+ if (mNextp)
+ {
+ mNextp->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, &(*ldata)->mListp);
+ }
+ }
+ break;
+ case LSCP_EMIT_CIL_ASSEMBLY:
+
+ // Load arguments.
+ mEntry1->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ if(is_SA_constant_integer(mEntry1))
+ {
+ print_cil_cast(fp, LST_INTEGER, LST_FLOATINGPOINT);
+ }
+ mEntry2->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ if(is_SA_constant_integer(mEntry3))
+ {
+ print_cil_cast(fp, LST_INTEGER, LST_FLOATINGPOINT);
+ }
+ mEntry3->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ if(is_SA_constant_integer(mEntry3))
+ {
+ print_cil_cast(fp, LST_INTEGER, LST_FLOATINGPOINT);
+ }
+
+ // Call named ctor, which leaves new Vector on stack, so it can be saved in to local or argument just like a primitive type.
+ fprintf(fp, "call valuetype [LScriptLibrary]LLVector valuetype [LScriptLibrary]LLVector::'create'(float32, float32, float32)\n");
+
+ // Next.
+ if (mNextp)
+ {
+ mNextp->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ }
+ break;
+ default:
+ mEntry3->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mEntry2->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mEntry1->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ if (mNextp)
+ {
+ mNextp->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ }
+ break;
+ }
+}
+
+S32 LLScriptSAVector::getSize()
+{
+ return mEntry1->getSize() + mEntry2->getSize() + mEntry3->getSize();
+}
+
+void LLScriptSAQuaternion::recurse(FILE *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)
+{
+ if (gErrorToText.getErrors())
+ {
+ return;
+ }
+ switch(pass)
+ {
+ case LSCP_PRETTY_PRINT:
+ case LSCP_EMIT_ASSEMBLY:
+ fprintf(fp, "< ");
+ mEntry4->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, ", ");
+ mEntry3->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, ", ");
+ mEntry2->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, ", ");
+ mEntry1->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, " >");
+ if (mNextp)
+ {
+ fprintf(fp, ", ");
+ mNextp->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ }
+ break;
+ case LSCP_TYPE:
+ // vector's take floats
+ mEntry4->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ if (!legal_assignment(LST_FLOATINGPOINT, type))
+ {
+ gErrorToText.writeError(fp, this, LSERROR_TYPE_MISMATCH);
+ }
+ mEntry3->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ if (!legal_assignment(LST_FLOATINGPOINT, type))
+ {
+ gErrorToText.writeError(fp, this, LSERROR_TYPE_MISMATCH);
+ }
+ mEntry2->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ if (!legal_assignment(LST_FLOATINGPOINT, type))
+ {
+ gErrorToText.writeError(fp, this, LSERROR_TYPE_MISMATCH);
+ }
+ mEntry1->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ if (!legal_assignment(LST_FLOATINGPOINT, type))
+ {
+ gErrorToText.writeError(fp, this, LSERROR_TYPE_MISMATCH);
+ }
+ type = LST_QUATERNION;
+ if (mNextp)
+ {
+ mNextp->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ }
+ break;
+ case LSCP_EMIT_BYTE_CODE:
+ mEntry4->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ if (type == LST_INTEGER)
+ {
+ S32 offset = chunk->mCurrentOffset - 4;
+ bytestream_int2float(chunk->mCodeChunk, offset);
+ }
+ mEntry3->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ if (type == LST_INTEGER)
+ {
+ S32 offset = chunk->mCurrentOffset - 4;
+ bytestream_int2float(chunk->mCodeChunk, offset);
+ }
+ mEntry2->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ if (type == LST_INTEGER)
+ {
+ S32 offset = chunk->mCurrentOffset - 4;
+ bytestream_int2float(chunk->mCodeChunk, offset);
+ }
+ mEntry1->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ if (type == LST_INTEGER)
+ {
+ S32 offset = chunk->mCurrentOffset - 4;
+ bytestream_int2float(chunk->mCodeChunk, offset);
+ }
+ if (mNextp)
+ {
+ mNextp->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ }
+ break;
+ case LSCP_LIST_BUILD_SIMPLE:
+ {
+ LLScriptByteCodeChunk *list = new LLScriptByteCodeChunk(FALSE);
+ mEntry4->recurse(fp, tabs, tabsize, LSCP_EMIT_BYTE_CODE, ptype, prunearg, scope, type, basetype, count, list, heap, stacksize, entry, entrycount, NULL);
+ if (type == LST_INTEGER)
+ {
+ S32 offset = list->mCurrentOffset - 4;
+ bytestream_int2float(list->mCodeChunk, offset);
+ }
+ mEntry3->recurse(fp, tabs, tabsize, LSCP_EMIT_BYTE_CODE, ptype, prunearg, scope, type, basetype, count, list, heap, stacksize, entry, entrycount, NULL);
+ if (type == LST_INTEGER)
+ {
+ S32 offset = list->mCurrentOffset - 4;
+ bytestream_int2float(list->mCodeChunk, offset);
+ }
+ mEntry2->recurse(fp, tabs, tabsize, LSCP_EMIT_BYTE_CODE, ptype, prunearg, scope, type, basetype, count, list, heap, stacksize, entry, entrycount, NULL);
+ if (type == LST_INTEGER)
+ {
+ S32 offset = list->mCurrentOffset - 4;
+ bytestream_int2float(list->mCodeChunk, offset);
+ }
+ mEntry1->recurse(fp, tabs, tabsize, LSCP_EMIT_BYTE_CODE, ptype, prunearg, scope, type, basetype, count, list, heap, stacksize, entry, entrycount, NULL);
+ if (type == LST_INTEGER)
+ {
+ S32 offset = list->mCurrentOffset - 4;
+ bytestream_int2float(list->mCodeChunk, offset);
+ }
+ LLQuaternion quat;
+ S32 offset = 0;
+ bytestream2quaternion(quat, list->mCodeChunk, offset);
+ *ldata = new LLScriptLibData(quat);
+ delete list;
+ if (mNextp)
+ {
+ mNextp->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, &(*ldata)->mListp);
+ }
+ }
+ break;
+ case LSCP_EMIT_CIL_ASSEMBLY:
+
+ // Load arguments.
+ mEntry1->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ if(is_SA_constant_integer(mEntry1))
+ {
+ print_cil_cast(fp, LST_INTEGER, LST_FLOATINGPOINT);
+ }
+ mEntry2->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ if(is_SA_constant_integer(mEntry2))
+ {
+ print_cil_cast(fp, LST_INTEGER, LST_FLOATINGPOINT);
+ }
+ mEntry3->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ if(is_SA_constant_integer(mEntry3))
+ {
+ print_cil_cast(fp, LST_INTEGER, LST_FLOATINGPOINT);
+ }
+ mEntry4->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ if(is_SA_constant_integer(mEntry4))
+ {
+ print_cil_cast(fp, LST_INTEGER, LST_FLOATINGPOINT);
+ }
+
+ // Call named ctor, which leaves new Vector on stack, so it can be saved in to local or argument just like a primitive type.
+ fprintf(fp, "call valuetype [LScriptLibrary]LLQuaternion valuetype [LScriptLibrary]LLQuaternion::'create'(float32, float32, float32, float32)\n");
+
+ // Next.
+ if (mNextp)
+ {
+ mNextp->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ }
+ break;
+ default:
+ mEntry4->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mEntry3->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mEntry2->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mEntry1->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ if (mNextp)
+ {
+ mNextp->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ }
+ break;
+ }
+}
+
+S32 LLScriptSAQuaternion::getSize()
+{
+ return mEntry1->getSize() + mEntry2->getSize() + mEntry3->getSize() + mEntry4->getSize();
+}
+
+void LLScriptSAList::recurse(FILE *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)
+{
+ if (gErrorToText.getErrors())
+ {
+ return;
+ }
+ switch(pass)
+ {
+ case LSCP_PRETTY_PRINT:
+ case LSCP_EMIT_ASSEMBLY:
+ fprintf(fp, "[ ");
+ if (mEntryList)
+ mEntryList->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, " ]");
+ if (mNextp)
+ {
+ fprintf(fp, ", ");
+ mNextp->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ }
+ break;
+ case LSCP_TYPE:
+ if (mEntryList)
+ mEntryList->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ type = LST_LIST;
+ if (mNextp)
+ {
+ mNextp->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ }
+ break;
+ case LSCP_EMIT_BYTE_CODE:
+ {
+ LLScriptLibData *list_data = new LLScriptLibData;
+
+ list_data->mType = LST_LIST;
+ if (mEntryList)
+ mEntryList->recurse(fp, tabs, tabsize, LSCP_LIST_BUILD_SIMPLE, ptype, prunearg, scope, type, basetype, count, chunk, NULL, stacksize, entry, entrycount, &(list_data->mListp));
+
+ U8 *temp;
+ chunk->addInteger(heap->mCurrentOffset + 1);
+ S32 size = lsa_create_data_block(&temp, list_data, heap->mCurrentOffset);
+ heap->addBytes(temp, size);
+ delete list_data;
+ delete [] temp;
+
+ if (mNextp)
+ {
+ mNextp->recurse(fp, tabs, tabsize, LSCP_EMIT_BYTE_CODE, ptype, prunearg, scope, type, basetype, count, chunk, NULL, stacksize, entry, entrycount, NULL);
+ }
+ }
+ break;
+ default:
+ if (mEntryList)
+ mEntryList->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, ldata);
+ if (mNextp)
+ {
+ mNextp->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, ldata);
+ }
+ break;
+ }
+}
+
+S32 LLScriptSAList::getSize()
+{
+ return mEntryList->getSize();
+}
+
+void LLScriptGlobalVariable::addGlobal(LLScriptGlobalVariable *global)
+{
+ if (mNextp)
+ {
+ global->mNextp = mNextp;
+ }
+ mNextp = global;
+}
+
+void LLScriptGlobalVariable::gonext(FILE *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)
+{
+ switch(pass)
+ {
+ case LSCP_PRETTY_PRINT:
+ if (mNextp)
+ {
+ mNextp->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ }
+ break;
+ default:
+ if (mNextp)
+ {
+ mNextp->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ }
+ break;
+ }
+}
+
+void LLScriptGlobalVariable::recurse(FILE *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)
+{
+ if (gErrorToText.getErrors())
+ {
+ return;
+ }
+ switch(pass)
+ {
+ case LSCP_PRETTY_PRINT:
+ mType->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp,"\t");
+ mIdentifier->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ if (mAssignable)
+ {
+ fprintf(fp, " = ");
+ mAssignable->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ }
+ fprintf(fp, ";\n");
+ break;
+ case LSCP_EMIT_ASSEMBLY:
+ mType->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp,"\t");
+ mIdentifier->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ if (mAssignable)
+ {
+ fprintf(fp, " = ");
+ mAssignable->recurse(fp, tabs, tabsize, LSCP_PRETTY_PRINT, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, "\n");
+ fprintf(fp, "Offset: %d Type: %d\n", mIdentifier->mScopeEntry->mOffset, (S32)LSCRIPTTypeByte[mType->mType]);
+ }
+ else
+ {
+ fprintf(fp, "\n");
+ fprintf(fp, "Offset: %d Type: %d\n", mIdentifier->mScopeEntry->mOffset, (S32)LSCRIPTTypeByte[mType->mType]);
+ }
+ break;
+ case LSCP_SCOPE_PASS1:
+ if (scope->checkEntry(mIdentifier->mName))
+ {
+ gErrorToText.writeError(fp, this, LSERROR_DUPLICATE_NAME);
+ }
+ else
+ {
+ if (mAssignable)
+ {
+ mAssignable->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ }
+ // this needs to go after expression decent to make sure that we don't add ourselves or something silly
+ mIdentifier->mScopeEntry = scope->addEntry(mIdentifier->mName, LIT_GLOBAL, mType->mType);
+ if (mIdentifier->mScopeEntry && mAssignable)
+ mIdentifier->mScopeEntry->mAssignable = mAssignable;
+ }
+ break;
+ case LSCP_TYPE:
+ // if the variable has an assignable, it must assignable to the variable's type
+ if (mAssignable)
+ {
+ mAssignable->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mAssignableType = type;
+ if (!legal_assignment(mType->mType, mAssignableType))
+ {
+ gErrorToText.writeError(fp, this, LSERROR_TYPE_MISMATCH);
+ }
+ }
+ break;
+ case LSCP_RESOURCE:
+ {
+ // we're just tryng to determine how much space the variable needs
+ // it also includes the name of the variable as well as the type
+ // plus 4 bytes of offset from it's apparent address to the actual data
+#ifdef LSL_INCLUDE_DEBUG_INFO
+ count += strlen(mIdentifier->mName) + 1 + 1 + 4;
+#else
+ count += 1 + 1 + 4;
+#endif
+ mIdentifier->mScopeEntry->mOffset = (S32)count;
+ mIdentifier->mScopeEntry->mSize = mType->getSize();
+ count += mIdentifier->mScopeEntry->mSize;
+ mIdentifier->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ }
+ break;
+ case LSCP_EMIT_BYTE_CODE:
+ {
+ // order for global variables
+ // 0 - 4: offset to actual data
+ S32 offsetoffset = chunk->mCurrentOffset;
+ S32 offsetdelta = 0;
+ chunk->addBytes(4);
+ // type
+ char vtype;
+ vtype = LSCRIPTTypeByte[mType->mType];
+ chunk->addBytes(&vtype, 1);
+ // null terminated name
+#ifdef LSL_INCLUDE_DEBUG_INFO
+ chunk->addBytes(mIdentifier->mName, strlen(mIdentifier->mName) + 1);
+#else
+ chunk->addBytes(1);
+#endif
+ // put correct offset delta in
+ offsetdelta = chunk->mCurrentOffset - offsetoffset;
+ integer2bytestream(chunk->mCodeChunk, offsetoffset, offsetdelta);
+
+ // now we need space for the variable itself
+ LLScriptByteCodeChunk *value = new LLScriptByteCodeChunk(FALSE);
+ if (mAssignable)
+ {
+ mAssignable->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, value, heap, stacksize, entry, entrycount, NULL);
+ // need to put sneaky type conversion here
+ if (mAssignableType != mType->mType)
+ {
+ // the only legal case that is a problem is int->float
+ if (mType->mType == LST_FLOATINGPOINT && mAssignableType == LST_INTEGER)
+ {
+ S32 offset = value->mCurrentOffset - 4;
+ bytestream_int2float(value->mCodeChunk, offset);
+ }
+ }
+ }
+ else
+ {
+ if ( (mType->mType == LST_STRING)
+ ||(mType->mType == LST_KEY))
+ {
+ // string and keys (even empty ones) need heap entries
+ chunk->addInteger(heap->mCurrentOffset + 1);
+ LLScriptLibData *data = new LLScriptLibData("");
+ U8 *temp;
+ S32 size = lsa_create_data_block(&temp, data, heap->mCurrentOffset);
+
+ heap->addBytes(temp, size);
+ delete [] temp;
+ delete data;
+ }
+ else if (mType->mType == LST_LIST)
+ {
+ chunk->addInteger(heap->mCurrentOffset + 1);
+ LLScriptLibData *data = new LLScriptLibData;
+ data->mType = LST_LIST;
+ U8 *temp;
+ S32 size = lsa_create_data_block(&temp, data, heap->mCurrentOffset);
+
+ heap->addBytes(temp, size);
+ delete [] temp;
+ delete data;
+ }
+ else if (mType->mType == LST_QUATERNION)
+ {
+ chunk->addFloat(1.f);
+ chunk->addFloat(0.f);
+ chunk->addFloat(0.f);
+ chunk->addFloat(0.f);
+ }
+ else
+ {
+ value->addBytes(LSCRIPTDataSize[mType->mType]);
+ }
+ }
+ chunk->addBytes(value->mCodeChunk, value->mCurrentOffset);
+ delete value;
+ }
+ break;
+ case LSCP_EMIT_CIL_ASSEMBLY:
+
+ // Initialisation inside ctor.
+ if (mAssignable)
+ {
+ fprintf(fp, "ldarg.0\n");
+ mAssignable->recurse(fp, tabs, tabsize, LSCP_EMIT_CIL_ASSEMBLY, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, "stfld ");
+ mType->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp," LSL::");
+ mIdentifier->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, "\n");
+ }
+ break;
+ default:
+ mType->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mIdentifier->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ if (mAssignable)
+ {
+ mAssignable->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ }
+ break;
+ }
+ gonext(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+}
+
+S32 LLScriptGlobalVariable::getSize()
+{
+ S32 return_size;
+
+ return_size = mType->getSize();
+ return return_size;
+}
+
+void LLScriptEvent::recurse(FILE *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)
+{
+ fprintf(fp, "Event Base Class -- should never get here!\n");
+}
+
+S32 LLScriptEvent::getSize()
+{
+ printf("Event Base Class -- should never get here!\n");
+ return 0;
+}
+
+void LLScriptStateEntryEvent::recurse(FILE *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)
+{
+ if (gErrorToText.getErrors())
+ {
+ return;
+ }
+ switch(pass)
+ {
+ case LSCP_PRETTY_PRINT:
+ fdotabs(fp, tabs, tabsize);
+ fprintf(fp, "state_entry()\n");
+ break;
+ case LSCP_EMIT_ASSEMBLY:
+ fprintf(fp, "state_entry()\n");
+ break;
+ case LSCP_EMIT_BYTE_CODE:
+ {
+#ifdef LSL_INCLUDE_DEBUG_INFO
+ char name[] = "state_entry";
+ chunk->addBytes(name, strlen(name) + 1);
+#endif
+ }
+ break;
+ case LSCP_EMIT_CIL_ASSEMBLY:
+ fprintf(fp, "state_entry()");
+ break;
+ default:
+ break;
+ }
+}
+
+S32 LLScriptStateEntryEvent::getSize()
+{
+ return 0;
+}
+
+void LLScriptStateExitEvent::recurse(FILE *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)
+{
+ if (gErrorToText.getErrors())
+ {
+ return;
+ }
+ switch(pass)
+ {
+ case LSCP_PRETTY_PRINT:
+ fdotabs(fp, tabs, tabsize);
+ fprintf(fp, "state_exit()\n");
+ break;
+ case LSCP_EMIT_ASSEMBLY:
+ fprintf(fp, "state_exit()\n");
+ break;
+ case LSCP_EMIT_BYTE_CODE:
+ {
+#ifdef LSL_INCLUDE_DEBUG_INFO
+ char name[] = "state_exit";
+ chunk->addBytes(name, strlen(name) + 1);
+#endif
+ }
+ break;
+ case LSCP_EMIT_CIL_ASSEMBLY:
+ fprintf(fp, "state_exit()");
+ break;
+ default:
+ break;
+ }
+}
+
+S32 LLScriptStateExitEvent::getSize()
+{
+ return 0;
+}
+
+void LLScriptTouchStartEvent::recurse(FILE *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)
+{
+ if (gErrorToText.getErrors())
+ {
+ return;
+ }
+ switch(pass)
+ {
+ case LSCP_PRETTY_PRINT:
+ case LSCP_EMIT_ASSEMBLY:
+ fdotabs(fp, tabs, tabsize);
+ fprintf(fp, "touch_start( integer ");
+ mCount->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, " )\n");
+ break;
+ break;
+ case LSCP_SCOPE_PASS1:
+ if (scope->checkEntry(mCount->mName))
+ {
+ gErrorToText.writeError(fp, this, LSERROR_DUPLICATE_NAME);
+ }
+ else
+ {
+ mCount->mScopeEntry = scope->addEntry(mCount->mName, LIT_VARIABLE, LST_INTEGER);
+ }
+ break;
+ case LSCP_RESOURCE:
+ {
+ // we're just tryng to determine how much space the variable needs
+ if (mCount->mScopeEntry)
+ {
+ mCount->mScopeEntry->mOffset = (S32)count;
+ mCount->mScopeEntry->mSize = 4;
+ count += mCount->mScopeEntry->mSize;
+ }
+ }
+ break;
+ case LSCP_EMIT_BYTE_CODE:
+ {
+#ifdef LSL_INCLUDE_DEBUG_INFO
+ char name[] = "touch_start";
+ chunk->addBytes(name, strlen(name) + 1);
+ chunk->addBytes(mCount->mName, strlen(mCount->mName) + 1);
+#endif
+ }
+ break;
+ default:
+ mCount->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ break;
+ }
+}
+
+S32 LLScriptTouchStartEvent::getSize()
+{
+ // integer = 4
+ return 4;
+}
+
+void LLScriptTouchEvent::recurse(FILE *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)
+{
+ if (gErrorToText.getErrors())
+ {
+ return;
+ }
+ switch(pass)
+ {
+ case LSCP_PRETTY_PRINT:
+ case LSCP_EMIT_ASSEMBLY:
+ fdotabs(fp, tabs, tabsize);
+ fprintf(fp, "touch( integer ");
+ mCount->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, " )\n");
+ break;
+ break;
+ case LSCP_SCOPE_PASS1:
+ if (scope->checkEntry(mCount->mName))
+ {
+ gErrorToText.writeError(fp, this, LSERROR_DUPLICATE_NAME);
+ }
+ else
+ {
+ mCount->mScopeEntry = scope->addEntry(mCount->mName, LIT_VARIABLE, LST_INTEGER);
+ }
+ break;
+ case LSCP_RESOURCE:
+ {
+ // we're just tryng to determine how much space the variable needs
+ if (mCount->mScopeEntry)
+ {
+ mCount->mScopeEntry->mOffset = (S32)count;
+ mCount->mScopeEntry->mSize = 4;
+ count += mCount->mScopeEntry->mSize;
+ }
+ }
+ break;
+ case LSCP_EMIT_BYTE_CODE:
+ {
+#ifdef LSL_INCLUDE_DEBUG_INFO
+ char name[] = "touch";
+ chunk->addBytes(name, strlen(name) + 1);
+ chunk->addBytes(mCount->mName, strlen(mCount->mName) + 1);
+#endif
+ }
+ break;
+ default:
+ mCount->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ break;
+ }
+}
+
+S32 LLScriptTouchEvent::getSize()
+{
+ // integer = 4
+ return 4;
+}
+
+void LLScriptTouchEndEvent::recurse(FILE *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)
+{
+ if (gErrorToText.getErrors())
+ {
+ return;
+ }
+ switch(pass)
+ {
+ case LSCP_PRETTY_PRINT:
+ case LSCP_EMIT_ASSEMBLY:
+ fdotabs(fp, tabs, tabsize);
+ fprintf(fp, "touch_end( integer ");
+ mCount->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, " )\n");
+ break;
+ break;
+ case LSCP_SCOPE_PASS1:
+ if (scope->checkEntry(mCount->mName))
+ {
+ gErrorToText.writeError(fp, this, LSERROR_DUPLICATE_NAME);
+ }
+ else
+ {
+ mCount->mScopeEntry = scope->addEntry(mCount->mName, LIT_VARIABLE, LST_INTEGER);
+ }
+ break;
+ case LSCP_RESOURCE:
+ {
+ // we're just tryng to determine how much space the variable needs
+ if (mCount->mScopeEntry)
+ {
+ mCount->mScopeEntry->mOffset = (S32)count;
+ mCount->mScopeEntry->mSize = 4;
+ count += mCount->mScopeEntry->mSize;
+ }
+ }
+ break;
+ case LSCP_EMIT_BYTE_CODE:
+ {
+#ifdef LSL_INCLUDE_DEBUG_INFO
+ char name[] = "touch_end";
+ chunk->addBytes(name, strlen(name) + 1);
+ chunk->addBytes(mCount->mName, strlen(mCount->mName) + 1);
+#endif
+ }
+ break;
+ default:
+ mCount->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ break;
+ }
+}
+
+S32 LLScriptTouchEndEvent::getSize()
+{
+ // integer = 4
+ return 4;
+}
+
+void LLScriptCollisionStartEvent::recurse(FILE *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)
+{
+ if (gErrorToText.getErrors())
+ {
+ return;
+ }
+ switch(pass)
+ {
+ case LSCP_PRETTY_PRINT:
+ case LSCP_EMIT_ASSEMBLY:
+ fdotabs(fp, tabs, tabsize);
+ fprintf(fp, "collision_start( integer ");
+ mCount->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, " )\n");
+ break;
+ break;
+ case LSCP_SCOPE_PASS1:
+ if (scope->checkEntry(mCount->mName))
+ {
+ gErrorToText.writeError(fp, this, LSERROR_DUPLICATE_NAME);
+ }
+ else
+ {
+ mCount->mScopeEntry = scope->addEntry(mCount->mName, LIT_VARIABLE, LST_INTEGER);
+ }
+ break;
+ case LSCP_RESOURCE:
+ {
+ // we're just tryng to determine how much space the variable needs
+ if (mCount->mScopeEntry)
+ {
+ mCount->mScopeEntry->mOffset = (S32)count;
+ mCount->mScopeEntry->mSize = 4;
+ count += mCount->mScopeEntry->mSize;
+ }
+ }
+ break;
+ case LSCP_EMIT_BYTE_CODE:
+ {
+#ifdef LSL_INCLUDE_DEBUG_INFO
+ char name[] = "collision_start";
+ chunk->addBytes(name, (S32)strlen(name) + 1);
+ chunk->addBytes(mCount->mName, (S32)strlen(mCount->mName) + 1);
+#endif
+ }
+ break;
+ default:
+ mCount->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ break;
+ }
+}
+
+S32 LLScriptCollisionStartEvent::getSize()
+{
+ // integer = 4
+ return 4;
+}
+
+void LLScriptCollisionEvent::recurse(FILE *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)
+{
+ if (gErrorToText.getErrors())
+ {
+ return;
+ }
+ switch(pass)
+ {
+ case LSCP_PRETTY_PRINT:
+ case LSCP_EMIT_ASSEMBLY:
+ fdotabs(fp, tabs, tabsize);
+ fprintf(fp, "collision( integer ");
+ mCount->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, " )\n");
+ break;
+ break;
+ case LSCP_SCOPE_PASS1:
+ if (scope->checkEntry(mCount->mName))
+ {
+ gErrorToText.writeError(fp, this, LSERROR_DUPLICATE_NAME);
+ }
+ else
+ {
+ mCount->mScopeEntry = scope->addEntry(mCount->mName, LIT_VARIABLE, LST_INTEGER);
+ }
+ break;
+ case LSCP_RESOURCE:
+ {
+ // we're just tryng to determine how much space the variable needs
+ if (mCount->mScopeEntry)
+ {
+ mCount->mScopeEntry->mOffset = (S32)count;
+ mCount->mScopeEntry->mSize = 4;
+ count += mCount->mScopeEntry->mSize;
+ }
+ }
+ break;
+ case LSCP_EMIT_BYTE_CODE:
+ {
+#ifdef LSL_INCLUDE_DEBUG_INFO
+ char name[] = "collision";
+ chunk->addBytes(name, strlen(name) + 1);
+ chunk->addBytes(mCount->mName, strlen(mCount->mName) + 1);
+#endif
+ }
+ break;
+ default:
+ mCount->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ break;
+ }
+}
+
+S32 LLScriptCollisionEvent::getSize()
+{
+ // integer = 4
+ return 4;
+}
+
+void LLScriptCollisionEndEvent::recurse(FILE *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)
+{
+ if (gErrorToText.getErrors())
+ {
+ return;
+ }
+ switch(pass)
+ {
+ case LSCP_PRETTY_PRINT:
+ case LSCP_EMIT_ASSEMBLY:
+ fdotabs(fp, tabs, tabsize);
+ fprintf(fp, "collision_end( integer ");
+ mCount->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, " )\n");
+ break;
+ break;
+ case LSCP_SCOPE_PASS1:
+ if (scope->checkEntry(mCount->mName))
+ {
+ gErrorToText.writeError(fp, this, LSERROR_DUPLICATE_NAME);
+ }
+ else
+ {
+ mCount->mScopeEntry = scope->addEntry(mCount->mName, LIT_VARIABLE, LST_INTEGER);
+ }
+ break;
+ case LSCP_RESOURCE:
+ {
+ // we're just tryng to determine how much space the variable needs
+ if (mCount->mScopeEntry)
+ {
+ mCount->mScopeEntry->mOffset = (S32)count;
+ mCount->mScopeEntry->mSize = 4;
+ count += mCount->mScopeEntry->mSize;
+ }
+ }
+ break;
+ case LSCP_EMIT_BYTE_CODE:
+ {
+#ifdef LSL_INCLUDE_DEBUG_INFO
+ char name[] = "collision_end";
+ chunk->addBytes(name, strlen(name) + 1);
+ chunk->addBytes(mCount->mName, strlen(mCount->mName) + 1);
+#endif
+ }
+ break;
+ default:
+ mCount->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ break;
+ }
+}
+
+S32 LLScriptCollisionEndEvent::getSize()
+{
+ // integer = 4
+ return 4;
+}
+
+void LLScriptLandCollisionStartEvent::recurse(FILE *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)
+{
+ if (gErrorToText.getErrors())
+ {
+ return;
+ }
+ switch(pass)
+ {
+ case LSCP_PRETTY_PRINT:
+ case LSCP_EMIT_ASSEMBLY:
+ fdotabs(fp, tabs, tabsize);
+ fprintf(fp, "land_collision_start( vector ");
+ mPosition->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, " )\n");
+ break;
+ case LSCP_SCOPE_PASS1:
+ if (scope->checkEntry(mPosition->mName))
+ {
+ gErrorToText.writeError(fp, this, LSERROR_DUPLICATE_NAME);
+ }
+ else
+ {
+ mPosition->mScopeEntry = scope->addEntry(mPosition->mName, LIT_VARIABLE, LST_VECTOR);
+ }
+ break;
+ case LSCP_RESOURCE:
+ {
+ // we're just tryng to determine how much space the variable needs
+ if (mPosition->mScopeEntry)
+ {
+ mPosition->mScopeEntry->mOffset = (S32)count;
+ mPosition->mScopeEntry->mSize = 12;
+ count += mPosition->mScopeEntry->mSize;
+ }
+ }
+ break;
+ case LSCP_EMIT_BYTE_CODE:
+ {
+#ifdef LSL_INCLUDE_DEBUG_INFO
+ char name[] = "land_collision_start";
+ chunk->addBytes(name, strlen(name) + 1);
+ chunk->addBytes(mPosition->mName, strlen(mPosition->mName) + 1);
+#endif
+ }
+ break;
+ default:
+ mPosition->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ break;
+ }
+}
+
+S32 LLScriptLandCollisionStartEvent::getSize()
+{
+ // vector = 12
+ return 12;
+}
+
+
+
+void LLScriptLandCollisionEvent::recurse(FILE *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)
+{
+ if (gErrorToText.getErrors())
+ {
+ return;
+ }
+ switch(pass)
+ {
+ case LSCP_PRETTY_PRINT:
+ case LSCP_EMIT_ASSEMBLY:
+ fdotabs(fp, tabs, tabsize);
+ fprintf(fp, "land_collision( vector ");
+ mPosition->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, " )\n");
+ break;
+ case LSCP_SCOPE_PASS1:
+ if (scope->checkEntry(mPosition->mName))
+ {
+ gErrorToText.writeError(fp, this, LSERROR_DUPLICATE_NAME);
+ }
+ else
+ {
+ mPosition->mScopeEntry = scope->addEntry(mPosition->mName, LIT_VARIABLE, LST_VECTOR);
+ }
+ break;
+ case LSCP_RESOURCE:
+ {
+ // we're just tryng to determine how much space the variable needs
+ if (mPosition->mScopeEntry)
+ {
+ mPosition->mScopeEntry->mOffset = (S32)count;
+ mPosition->mScopeEntry->mSize = 12;
+ count += mPosition->mScopeEntry->mSize;
+ }
+ }
+ break;
+ case LSCP_EMIT_BYTE_CODE:
+ {
+#ifdef LSL_INCLUDE_DEBUG_INFO
+ char name[] = "land_collision";
+ chunk->addBytes(name, strlen(name) + 1);
+ chunk->addBytes(mPosition->mName, strlen(mPosition->mName) + 1);
+#endif
+ }
+ break;
+ default:
+ mPosition->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ break;
+ }
+}
+
+S32 LLScriptLandCollisionEvent::getSize()
+{
+ // vector = 12
+ return 12;
+}
+
+
+void LLScriptLandCollisionEndEvent::recurse(FILE *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)
+{
+ if (gErrorToText.getErrors())
+ {
+ return;
+ }
+ switch(pass)
+ {
+ case LSCP_PRETTY_PRINT:
+ case LSCP_EMIT_ASSEMBLY:
+ fdotabs(fp, tabs, tabsize);
+ fprintf(fp, "land_collision_end( vector ");
+ mPosition->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, " )\n");
+ break;
+ case LSCP_SCOPE_PASS1:
+ if (scope->checkEntry(mPosition->mName))
+ {
+ gErrorToText.writeError(fp, this, LSERROR_DUPLICATE_NAME);
+ }
+ else
+ {
+ mPosition->mScopeEntry = scope->addEntry(mPosition->mName, LIT_VARIABLE, LST_VECTOR);
+ }
+ break;
+ case LSCP_RESOURCE:
+ {
+ // we're just tryng to determine how much space the variable needs
+ if (mPosition->mScopeEntry)
+ {
+ mPosition->mScopeEntry->mOffset = (S32)count;
+ mPosition->mScopeEntry->mSize = 12;
+ count += mPosition->mScopeEntry->mSize;
+ }
+ }
+ break;
+ case LSCP_EMIT_BYTE_CODE:
+ {
+#ifdef LSL_INCLUDE_DEBUG_INFO
+ char name[] = "land_collision_end";
+ chunk->addBytes(name, strlen(name) + 1);
+ chunk->addBytes(mPosition->mName, strlen(mPosition->mName) + 1);
+#endif
+ }
+ break;
+ default:
+ mPosition->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ break;
+ }
+}
+
+S32 LLScriptLandCollisionEndEvent::getSize()
+{
+ // vector = 12
+ return 12;
+}
+
+
+void LLScriptInventoryEvent::recurse(FILE *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)
+{
+ if (gErrorToText.getErrors())
+ {
+ return;
+ }
+ switch(pass)
+ {
+ case LSCP_PRETTY_PRINT:
+ case LSCP_EMIT_ASSEMBLY:
+ fdotabs(fp, tabs, tabsize);
+ fprintf(fp, "changed( integer ");
+ mChange->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, " )\n");
+ break;
+ case LSCP_SCOPE_PASS1:
+ if (scope->checkEntry(mChange->mName))
+ {
+ gErrorToText.writeError(fp, this, LSERROR_DUPLICATE_NAME);
+ }
+ else
+ {
+ mChange->mScopeEntry = scope->addEntry(mChange->mName, LIT_VARIABLE, LST_INTEGER);
+ }
+ break;
+ case LSCP_RESOURCE:
+ {
+ // we're just tryng to determine how much space the variable needs
+ if (mChange->mScopeEntry)
+ {
+ mChange->mScopeEntry->mOffset = (S32)count;
+ mChange->mScopeEntry->mSize = 4;
+ count += mChange->mScopeEntry->mSize;
+ }
+ }
+ break;
+ case LSCP_EMIT_BYTE_CODE:
+ {
+#ifdef LSL_INCLUDE_DEBUG_INFO
+ char name[] = "changed";
+ chunk->addBytes(name, strlen(name) + 1);
+ chunk->addBytes(mChange->mName, strlen(mChange->mName) + 1);
+#endif
+ }
+ break;
+ default:
+ mChange->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ break;
+ }
+}
+
+S32 LLScriptInventoryEvent::getSize()
+{
+ // integer = 4
+ return 4;
+}
+
+void LLScriptAttachEvent::recurse(FILE *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)
+{
+ if (gErrorToText.getErrors())
+ {
+ return;
+ }
+ switch(pass)
+ {
+ case LSCP_PRETTY_PRINT:
+ case LSCP_EMIT_ASSEMBLY:
+ fdotabs(fp, tabs, tabsize);
+ fprintf(fp, "attach( key ");
+ mAttach->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, " )\n");
+ break;
+ case LSCP_SCOPE_PASS1:
+ if (scope->checkEntry(mAttach->mName))
+ {
+ gErrorToText.writeError(fp, this, LSERROR_DUPLICATE_NAME);
+ }
+ else
+ {
+ mAttach->mScopeEntry = scope->addEntry(mAttach->mName, LIT_VARIABLE, LST_KEY);
+ }
+ break;
+ case LSCP_RESOURCE:
+ {
+ // we're just tryng to determine how much space the variable needs
+ if (mAttach->mScopeEntry)
+ {
+ mAttach->mScopeEntry->mOffset = (S32)count;
+ mAttach->mScopeEntry->mSize = 4;
+ count += mAttach->mScopeEntry->mSize;
+ }
+ }
+ break;
+ case LSCP_EMIT_BYTE_CODE:
+ {
+#ifdef LSL_INCLUDE_DEBUG_INFO
+ char name[] = "attach";
+ chunk->addBytes(name, strlen(name) + 1);
+ chunk->addBytes(mAttach->mName, strlen(mAttach->mName) + 1);
+#endif
+ }
+ break;
+ default:
+ mAttach->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ break;
+ }
+}
+
+S32 LLScriptAttachEvent::getSize()
+{
+ // key = 4
+ return 4;
+}
+
+void LLScriptDataserverEvent::recurse(FILE *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)
+{
+ if (gErrorToText.getErrors())
+ {
+ return;
+ }
+ switch(pass)
+ {
+ case LSCP_PRETTY_PRINT:
+ case LSCP_EMIT_ASSEMBLY:
+ fdotabs(fp, tabs, tabsize);
+ fprintf(fp, "dataserver( key ");
+ mID->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, ", string ");
+ mData->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, " )\n");
+ break;
+ case LSCP_SCOPE_PASS1:
+ if (scope->checkEntry(mID->mName))
+ {
+ gErrorToText.writeError(fp, this, LSERROR_DUPLICATE_NAME);
+ }
+ else
+ {
+ mID->mScopeEntry = scope->addEntry(mID->mName, LIT_VARIABLE, LST_KEY);
+ }
+ if (scope->checkEntry(mData->mName))
+ {
+ gErrorToText.writeError(fp, this, LSERROR_DUPLICATE_NAME);
+ }
+ else
+ {
+ mData->mScopeEntry = scope->addEntry(mData->mName, LIT_VARIABLE, LST_STRING);
+ }
+ break;
+ case LSCP_RESOURCE:
+ {
+ // we're just tryng to determine how much space the variable needs
+ if (mID->mScopeEntry)
+ {
+ mID->mScopeEntry->mOffset = (S32)count;
+ mID->mScopeEntry->mSize = 4;
+ count += mID->mScopeEntry->mSize;
+ mData->mScopeEntry->mOffset = (S32)count;
+ mData->mScopeEntry->mSize = 4;
+ count += mData->mScopeEntry->mSize;
+ }
+ }
+ break;
+ case LSCP_EMIT_BYTE_CODE:
+ {
+#ifdef LSL_INCLUDE_DEBUG_INFO
+ char name[] = "dataserver";
+ chunk->addBytes(name, strlen(name) + 1);
+ chunk->addBytes(mID->mName, strlen(mID->mName) + 1);
+ chunk->addBytes(mData->mName, strlen(mData->mName) + 1);
+#endif
+ }
+ break;
+ default:
+ mID->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mData->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ break;
+ }
+}
+
+S32 LLScriptDataserverEvent::getSize()
+{
+ // key + string = 8
+ return 8;
+}
+
+void LLScriptTimerEvent::recurse(FILE *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)
+{
+ if (gErrorToText.getErrors())
+ {
+ return;
+ }
+ switch(pass)
+ {
+ case LSCP_PRETTY_PRINT:
+ fdotabs(fp, tabs, tabsize);
+ fprintf(fp, "timer()\n");
+ break;
+ case LSCP_EMIT_ASSEMBLY:
+ fprintf(fp, "timer()\n");
+ break;
+ case LSCP_EMIT_BYTE_CODE:
+ {
+#ifdef LSL_INCLUDE_DEBUG_INFO
+ char name[] = "timer";
+ chunk->addBytes(name, strlen(name) + 1);
+#endif
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+S32 LLScriptTimerEvent::getSize()
+{
+ return 0;
+}
+
+void LLScriptMovingStartEvent::recurse(FILE *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)
+{
+ if (gErrorToText.getErrors())
+ {
+ return;
+ }
+ switch(pass)
+ {
+ case LSCP_PRETTY_PRINT:
+ case LSCP_EMIT_ASSEMBLY:
+ fdotabs(fp, tabs, tabsize);
+ fprintf(fp, "moving_start()\n");
+ break;
+ case LSCP_EMIT_BYTE_CODE:
+ {
+#ifdef LSL_INCLUDE_DEBUG_INFO
+ char name[] = "moving_start";
+ chunk->addBytes(name, strlen(name) + 1);
+#endif
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+S32 LLScriptMovingStartEvent::getSize()
+{
+ return 0;
+}
+
+void LLScriptMovingEndEvent::recurse(FILE *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)
+{
+ if (gErrorToText.getErrors())
+ {
+ return;
+ }
+ switch(pass)
+ {
+ case LSCP_PRETTY_PRINT:
+ case LSCP_EMIT_ASSEMBLY:
+ fdotabs(fp, tabs, tabsize);
+ fprintf(fp, "moving_end()\n");
+ break;
+ case LSCP_EMIT_BYTE_CODE:
+ {
+#ifdef LSL_INCLUDE_DEBUG_INFO
+ char name[] = "moving_end";
+ chunk->addBytes(name, strlen(name) + 1);
+#endif
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+S32 LLScriptMovingEndEvent::getSize()
+{
+ return 0;
+}
+
+void LLScriptRTPEvent::recurse(FILE *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)
+{
+ if (gErrorToText.getErrors())
+ {
+ return;
+ }
+ switch(pass)
+ {
+ case LSCP_PRETTY_PRINT:
+ case LSCP_EMIT_ASSEMBLY:
+ fdotabs(fp, tabs, tabsize);
+ fprintf(fp, "chat( integer ");
+ mRTPermissions->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, " )\n");
+ break;
+ case LSCP_SCOPE_PASS1:
+ if (scope->checkEntry(mRTPermissions->mName))
+ {
+ gErrorToText.writeError(fp, this, LSERROR_DUPLICATE_NAME);
+ }
+ else
+ {
+ mRTPermissions->mScopeEntry = scope->addEntry(mRTPermissions->mName, LIT_VARIABLE, LST_INTEGER);
+ }
+ break;
+ case LSCP_RESOURCE:
+ {
+ // we're just tryng to determine how much space the variable needs
+ if (mRTPermissions->mScopeEntry)
+ {
+ mRTPermissions->mScopeEntry->mOffset = (S32)count;
+ mRTPermissions->mScopeEntry->mSize = 4;
+ count += mRTPermissions->mScopeEntry->mSize;
+ }
+ }
+ break;
+ case LSCP_EMIT_BYTE_CODE:
+ {
+#ifdef LSL_INCLUDE_DEBUG_INFO
+ char name[] = "chat";
+ chunk->addBytes(name, strlen(name) + 1);
+ chunk->addBytes(mRTPermissions->mName, strlen(mRTPermissions->mName) + 1);
+#endif
+ }
+ break;
+ default:
+ mRTPermissions->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ break;
+ }
+}
+
+S32 LLScriptRTPEvent::getSize()
+{
+ // integer = 4
+ return 4;
+}
+
+void LLScriptChatEvent::recurse(FILE *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)
+{
+ if (gErrorToText.getErrors())
+ {
+ return;
+ }
+ switch(pass)
+ {
+ case LSCP_PRETTY_PRINT:
+ case LSCP_EMIT_ASSEMBLY:
+ fdotabs(fp, tabs, tabsize);
+ fprintf(fp, "chat( integer ");
+ mChannel->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, ", string ");
+ mName->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, ", key ");
+ mID->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, ", string ");
+ mMessage->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, " )\n");
+ break;
+ case LSCP_SCOPE_PASS1:
+ if (scope->checkEntry(mChannel->mName))
+ {
+ gErrorToText.writeError(fp, this, LSERROR_DUPLICATE_NAME);
+ }
+ else
+ {
+ mChannel->mScopeEntry = scope->addEntry(mChannel->mName, LIT_VARIABLE, LST_INTEGER);
+ }
+ if (scope->checkEntry(mName->mName))
+ {
+ gErrorToText.writeError(fp, this, LSERROR_DUPLICATE_NAME);
+ }
+ else
+ {
+ mName->mScopeEntry = scope->addEntry(mName->mName, LIT_VARIABLE, LST_STRING);
+ }
+ if (scope->checkEntry(mID->mName))
+ {
+ gErrorToText.writeError(fp, this, LSERROR_DUPLICATE_NAME);
+ }
+ else
+ {
+ mID->mScopeEntry = scope->addEntry(mID->mName, LIT_VARIABLE, LST_KEY);
+ }
+ if (scope->checkEntry(mMessage->mName))
+ {
+ gErrorToText.writeError(fp, this, LSERROR_DUPLICATE_NAME);
+ }
+ else
+ {
+ mMessage->mScopeEntry = scope->addEntry(mMessage->mName, LIT_VARIABLE, LST_STRING);
+ }
+ break;
+ case LSCP_RESOURCE:
+ {
+ // we're just tryng to determine how much space the variable needs
+ if (mName->mScopeEntry)
+ {
+ mChannel->mScopeEntry->mOffset = (S32)count;
+ mChannel->mScopeEntry->mSize = 4;
+ count += mChannel->mScopeEntry->mSize;
+ mName->mScopeEntry->mOffset = (S32)count;
+ mName->mScopeEntry->mSize = 4;
+ count += mName->mScopeEntry->mSize;
+ mID->mScopeEntry->mOffset = (S32)count;
+ mID->mScopeEntry->mSize = 4;
+ count += mID->mScopeEntry->mSize;
+ mMessage->mScopeEntry->mOffset = (S32)count;
+ mMessage->mScopeEntry->mSize = 4;
+ count += mMessage->mScopeEntry->mSize;
+ }
+ }
+ break;
+ case LSCP_EMIT_BYTE_CODE:
+ {
+#ifdef LSL_INCLUDE_DEBUG_INFO
+ char name[] = "chat";
+ chunk->addBytes(name, strlen(name) + 1);
+ chunk->addBytes(mChannel->mName, strlen(mChannel->mName) + 1);
+ chunk->addBytes(mName->mName, strlen(mName->mName) + 1);
+ chunk->addBytes(mID->mName, strlen(mID->mName) + 1);
+ chunk->addBytes(mMessage->mName, strlen(mMessage->mName) + 1);
+#endif
+ }
+ break;
+ default:
+ mChannel->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mName->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mID->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mMessage->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ break;
+ }
+}
+
+S32 LLScriptChatEvent::getSize()
+{
+ // integer + key + string + string = 16
+ return 16;
+}
+
+void LLScriptSensorEvent::recurse(FILE *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)
+{
+ if (gErrorToText.getErrors())
+ {
+ return;
+ }
+ switch(pass)
+ {
+ case LSCP_PRETTY_PRINT:
+ case LSCP_EMIT_ASSEMBLY:
+ fdotabs(fp, tabs, tabsize);
+ fprintf(fp, "sensor( integer ");
+ mNumber->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, " )\n");
+ break;
+ case LSCP_SCOPE_PASS1:
+ if (scope->checkEntry(mNumber->mName))
+ {
+ gErrorToText.writeError(fp, this, LSERROR_DUPLICATE_NAME);
+ }
+ else
+ {
+ mNumber->mScopeEntry = scope->addEntry(mNumber->mName, LIT_VARIABLE, LST_INTEGER);
+ }
+ break;
+ case LSCP_RESOURCE:
+ {
+ // we're just tryng to determine how much space the variable needs
+ if (mNumber->mScopeEntry)
+ {
+ mNumber->mScopeEntry->mOffset = (S32)count;
+ mNumber->mScopeEntry->mSize = 4;
+ count += mNumber->mScopeEntry->mSize;
+ }
+ }
+ break;
+ case LSCP_EMIT_BYTE_CODE:
+ {
+#ifdef LSL_INCLUDE_DEBUG_INFO
+ char name[] = "sensor";
+ chunk->addBytes(name, strlen(name) + 1);
+ chunk->addBytes(mNumber->mName, strlen(mNumber->mName) + 1);
+#endif
+ }
+ break;
+ default:
+ mNumber->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ break;
+ }
+}
+
+S32 LLScriptSensorEvent::getSize()
+{
+ // integer = 4
+ return 4;
+}
+
+void LLScriptObjectRezEvent::recurse(FILE *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)
+{
+ if (gErrorToText.getErrors())
+ {
+ return;
+ }
+ switch(pass)
+ {
+ case LSCP_PRETTY_PRINT:
+ case LSCP_EMIT_ASSEMBLY:
+ fdotabs(fp, tabs, tabsize);
+ fprintf(fp, "object_rez( key ");
+ mID->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, " )\n");
+ break;
+ case LSCP_SCOPE_PASS1:
+ if (scope->checkEntry(mID->mName))
+ {
+ gErrorToText.writeError(fp, this, LSERROR_DUPLICATE_NAME);
+ }
+ else
+ {
+ mID->mScopeEntry = scope->addEntry(mID->mName, LIT_VARIABLE, LST_KEY);
+ }
+ break;
+ case LSCP_RESOURCE:
+ {
+ // we're just tryng to determine how much space the variable needs
+ if (mID->mScopeEntry)
+ {
+ mID->mScopeEntry->mOffset = (S32)count;
+ mID->mScopeEntry->mSize = 4;
+ count += mID->mScopeEntry->mSize;
+ }
+ }
+ break;
+ case LSCP_EMIT_BYTE_CODE:
+ {
+#ifdef LSL_INCLUDE_DEBUG_INFO
+ char name[] = "sensor";
+ chunk->addBytes(name, strlen(name) + 1);
+ chunk->addBytes(mID->mName, strlen(mID->mName) + 1);
+#endif
+ }
+ break;
+ default:
+ mID->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ break;
+ }
+}
+
+S32 LLScriptObjectRezEvent::getSize()
+{
+ // key = 4
+ return 4;
+}
+
+void LLScriptControlEvent::recurse(FILE *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)
+{
+ if (gErrorToText.getErrors())
+ {
+ return;
+ }
+ switch(pass)
+ {
+ case LSCP_PRETTY_PRINT:
+ case LSCP_EMIT_ASSEMBLY:
+ fdotabs(fp, tabs, tabsize);
+ fprintf(fp, "control( key ");
+ mName->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, ", integer ");
+ mLevels->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, ", integer ");
+ mEdges->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, " )\n");
+ break;
+ case LSCP_SCOPE_PASS1:
+ if (scope->checkEntry(mName->mName))
+ {
+ gErrorToText.writeError(fp, this, LSERROR_DUPLICATE_NAME);
+ }
+ else
+ {
+ mName->mScopeEntry = scope->addEntry(mName->mName, LIT_VARIABLE, LST_KEY);
+ }
+ if (scope->checkEntry(mLevels->mName))
+ {
+ gErrorToText.writeError(fp, this, LSERROR_DUPLICATE_NAME);
+ }
+ else
+ {
+ mLevels->mScopeEntry = scope->addEntry(mLevels->mName, LIT_VARIABLE, LST_INTEGER);
+ }
+ if (scope->checkEntry(mEdges->mName))
+ {
+ gErrorToText.writeError(fp, this, LSERROR_DUPLICATE_NAME);
+ }
+ else
+ {
+ mEdges->mScopeEntry = scope->addEntry(mEdges->mName, LIT_VARIABLE, LST_INTEGER);
+ }
+ break;
+ case LSCP_RESOURCE:
+ {
+ // we're just tryng to determine how much space the variable needs
+ if (mName->mScopeEntry)
+ {
+ mName->mScopeEntry->mOffset = (S32)count;
+ mName->mScopeEntry->mSize = 4;
+ count += mName->mScopeEntry->mSize;
+ mLevels->mScopeEntry->mOffset = (S32)count;
+ mLevels->mScopeEntry->mSize = 4;
+ count += mLevels->mScopeEntry->mSize;
+ mEdges->mScopeEntry->mOffset = (S32)count;
+ mEdges->mScopeEntry->mSize = 4;
+ count += mEdges->mScopeEntry->mSize;
+ }
+ }
+ break;
+ case LSCP_EMIT_BYTE_CODE:
+ {
+#ifdef LSL_INCLUDE_DEBUG_INFO
+ char name[] = "control";
+ chunk->addBytes(name, strlen(name) + 1);
+ chunk->addBytes(mName->mName, strlen(mName->mName) + 1);
+ chunk->addBytes(mLevels->mName, strlen(mLevels->mName) + 1);
+ chunk->addBytes(mEdges->mName, strlen(mEdges->mName) + 1);
+#endif
+ }
+ break;
+ default:
+ mName->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mLevels->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mEdges->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ break;
+ }
+}
+
+S32 LLScriptControlEvent::getSize()
+{
+ // key + integer + integer = 12
+ return 12;
+}
+
+void LLScriptLinkMessageEvent::recurse(FILE *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)
+{
+ if (gErrorToText.getErrors())
+ {
+ return;
+ }
+ switch(pass)
+ {
+ case LSCP_PRETTY_PRINT:
+ case LSCP_EMIT_ASSEMBLY:
+ fdotabs(fp, tabs, tabsize);
+ fprintf(fp, "link_message( integer ");
+ mSender->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, ", integer ");
+ mNum->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, ", string ");
+ mStr->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, ", key ");
+ mID->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, " )\n");
+ break;
+ case LSCP_SCOPE_PASS1:
+ if (scope->checkEntry(mSender->mName))
+ {
+ gErrorToText.writeError(fp, this, LSERROR_DUPLICATE_NAME);
+ }
+ else
+ {
+ mSender->mScopeEntry = scope->addEntry(mSender->mName, LIT_VARIABLE, LST_INTEGER);
+ }
+ if (scope->checkEntry(mNum->mName))
+ {
+ gErrorToText.writeError(fp, this, LSERROR_DUPLICATE_NAME);
+ }
+ else
+ {
+ mNum->mScopeEntry = scope->addEntry(mNum->mName, LIT_VARIABLE, LST_INTEGER);
+ }
+ if (scope->checkEntry(mStr->mName))
+ {
+ gErrorToText.writeError(fp, this, LSERROR_DUPLICATE_NAME);
+ }
+ else
+ {
+ mStr->mScopeEntry = scope->addEntry(mStr->mName, LIT_VARIABLE, LST_STRING);
+ }
+ if (scope->checkEntry(mID->mName))
+ {
+ gErrorToText.writeError(fp, this, LSERROR_DUPLICATE_NAME);
+ }
+ else
+ {
+ mID->mScopeEntry = scope->addEntry(mID->mName, LIT_VARIABLE, LST_KEY);
+ }
+ break;
+ case LSCP_RESOURCE:
+ {
+ // we're just tryng to determine how much space the variable needs
+ if (mSender->mScopeEntry)
+ {
+ mSender->mScopeEntry->mOffset = (S32)count;
+ mSender->mScopeEntry->mSize = 4;
+ count += mSender->mScopeEntry->mSize;
+ mNum->mScopeEntry->mOffset = (S32)count;
+ mNum->mScopeEntry->mSize = 4;
+ count += mNum->mScopeEntry->mSize;
+ mStr->mScopeEntry->mOffset = (S32)count;
+ mStr->mScopeEntry->mSize = 4;
+ count += mStr->mScopeEntry->mSize;
+ mID->mScopeEntry->mOffset = (S32)count;
+ mID->mScopeEntry->mSize = 4;
+ count += mID->mScopeEntry->mSize;
+ }
+ }
+ break;
+ case LSCP_EMIT_BYTE_CODE:
+ {
+#ifdef LSL_INCLUDE_DEBUG_INFO
+ char name[] = "link_message";
+ chunk->addBytes(name, strlen(name) + 1);
+ chunk->addBytes(mSender->mName, strlen(mSender->mName) + 1);
+ chunk->addBytes(mNum->mName, strlen(mNum->mName) + 1);
+ chunk->addBytes(mStr->mName, strlen(mStr->mName) + 1);
+ chunk->addBytes(mID->mName, strlen(mID->mName) + 1);
+#endif
+ }
+ break;
+ default:
+ mSender->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mNum->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mStr->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mID->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ break;
+ }
+}
+
+S32 LLScriptLinkMessageEvent::getSize()
+{
+ // integer + key + integer + string = 16
+ return 16;
+}
+
+void LLScriptRemoteEvent::recurse(FILE *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)
+{
+ if (gErrorToText.getErrors())
+ {
+ return;
+ }
+ switch(pass)
+ {
+ case LSCP_PRETTY_PRINT:
+ case LSCP_EMIT_ASSEMBLY:
+ fdotabs(fp, tabs, tabsize);
+ fprintf(fp, "remote_event( integer ");
+ mType->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, ", key ");
+ mChannel->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, ", key ");
+ mMessageID->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, ", string ");
+ mSender->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, ", integer ");
+ mIntVal->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, ", string ");
+ mStrVal->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, " )\n");
+ break;
+ case LSCP_SCOPE_PASS1:
+ if (scope->checkEntry(mType->mName))
+ {
+ gErrorToText.writeError(fp, this, LSERROR_DUPLICATE_NAME);
+ }
+ else
+ {
+ mType->mScopeEntry = scope->addEntry(mType->mName, LIT_VARIABLE, LST_INTEGER);
+ }
+ if (scope->checkEntry(mChannel->mName))
+ {
+ gErrorToText.writeError(fp, this, LSERROR_DUPLICATE_NAME);
+ }
+ else
+ {
+ mChannel->mScopeEntry = scope->addEntry(mChannel->mName, LIT_VARIABLE, LST_KEY);
+ }
+ if (scope->checkEntry(mMessageID->mName))
+ {
+ gErrorToText.writeError(fp, this, LSERROR_DUPLICATE_NAME);
+ }
+ else
+ {
+ mMessageID->mScopeEntry = scope->addEntry(mMessageID->mName, LIT_VARIABLE, LST_KEY);
+ }
+ if (scope->checkEntry(mSender->mName))
+ {
+ gErrorToText.writeError(fp, this, LSERROR_DUPLICATE_NAME);
+ }
+ else
+ {
+ mSender->mScopeEntry = scope->addEntry(mSender->mName, LIT_VARIABLE, LST_STRING);
+ }
+ if (scope->checkEntry(mIntVal->mName))
+ {
+ gErrorToText.writeError(fp, this, LSERROR_DUPLICATE_NAME);
+ }
+ else
+ {
+ mIntVal->mScopeEntry = scope->addEntry(mIntVal->mName, LIT_VARIABLE, LST_INTEGER);
+ }
+ if (scope->checkEntry(mStrVal->mName))
+ {
+ gErrorToText.writeError(fp, this, LSERROR_DUPLICATE_NAME);
+ }
+ else
+ {
+ mStrVal->mScopeEntry = scope->addEntry(mStrVal->mName, LIT_VARIABLE, LST_STRING);
+ }
+ break;
+ case LSCP_RESOURCE:
+ {
+ // we're just tryng to determine how much space the variable needs
+ if (mType->mScopeEntry)
+ {
+ mType->mScopeEntry->mOffset = (S32)count;
+ mType->mScopeEntry->mSize = 4;
+ count += mType->mScopeEntry->mSize;
+ mChannel->mScopeEntry->mOffset = (S32)count;
+ mChannel->mScopeEntry->mSize = 4;
+ count += mChannel->mScopeEntry->mSize;
+ mMessageID->mScopeEntry->mOffset = (S32)count;
+ mMessageID->mScopeEntry->mSize = 4;
+ count += mMessageID->mScopeEntry->mSize;
+ mSender->mScopeEntry->mOffset = (S32)count;
+ mSender->mScopeEntry->mSize = 4;
+ count += mSender->mScopeEntry->mSize;
+ mIntVal->mScopeEntry->mOffset = (S32)count;
+ mIntVal->mScopeEntry->mSize = 4;
+ count += mIntVal->mScopeEntry->mSize;
+ mStrVal->mScopeEntry->mOffset = (S32)count;
+ mStrVal->mScopeEntry->mSize = 4;
+ count += mStrVal->mScopeEntry->mSize;
+ }
+ }
+ break;
+ case LSCP_EMIT_BYTE_CODE:
+ {
+#ifdef LSL_INCLUDE_DEBUG_INFO
+ char name[] = "remote_event";
+ chunk->addBytes(name, strlen(name) + 1);
+ chunk->addBytes(mType->mName, strlen(mType->mName) + 1);
+ chunk->addBytes(mChannel->mName, strlen(mChannel->mName) + 1);
+ chunk->addBytes(mMessageID->mName, strlen(mMessageID->mName) + 1);
+ chunk->addBytes(mSender->mName, strlen(mSender->mName) + 1);
+ chunk->addBytes(mIntVal->mName, strlen(mIntVal->mName) + 1);
+ chunk->addBytes(mStrVal->mName, strlen(mStrVal->mName) + 1);
+#endif
+ }
+ break;
+ default:
+ mType->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mChannel->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mMessageID->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mSender->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mIntVal->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mStrVal->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ break;
+ }
+}
+
+S32 LLScriptRemoteEvent::getSize()
+{
+ // integer + key + key + string + integer + string = 24
+ return 24;
+}
+
+void LLScriptHTTPResponseEvent::recurse(FILE *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)
+{
+ if (gErrorToText.getErrors())
+ {
+ return;
+ }
+ switch(pass)
+ {
+ case LSCP_PRETTY_PRINT:
+ case LSCP_EMIT_ASSEMBLY:
+ fdotabs(fp, tabs, tabsize);
+ fprintf(fp, "http_response( key ");
+ mRequestId->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, ", integer ");
+ mStatus->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, ", list ");
+ mMetadata->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, ", string ");
+ mBody->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, " )\n");
+ break;
+
+ case LSCP_SCOPE_PASS1:
+ if (scope->checkEntry(mRequestId->mName))
+ {
+ gErrorToText.writeError(fp, this, LSERROR_DUPLICATE_NAME);
+ }
+ else
+ {
+ mRequestId->mScopeEntry = scope->addEntry(mRequestId->mName, LIT_VARIABLE, LST_KEY);
+ }
+
+ if (scope->checkEntry(mStatus->mName))
+ {
+ gErrorToText.writeError(fp, this, LSERROR_DUPLICATE_NAME);
+ }
+ else
+ {
+ mStatus->mScopeEntry = scope->addEntry(mStatus->mName, LIT_VARIABLE, LST_INTEGER);
+ }
+
+ if (scope->checkEntry(mMetadata->mName))
+ {
+ gErrorToText.writeError(fp, this, LSERROR_DUPLICATE_NAME);
+ }
+ else
+ {
+ mMetadata->mScopeEntry = scope->addEntry(mMetadata->mName, LIT_VARIABLE, LST_LIST);
+ }
+
+ if (scope->checkEntry(mBody->mName))
+ {
+ gErrorToText.writeError(fp, this, LSERROR_DUPLICATE_NAME);
+ }
+ else
+ {
+ mBody->mScopeEntry = scope->addEntry(mBody->mName, LIT_VARIABLE, LST_STRING);
+ }
+ break;
+
+ case LSCP_RESOURCE:
+ {
+ // we're just tryng to determine how much space the variable needs
+ if (mRequestId->mScopeEntry)
+ {
+ mRequestId->mScopeEntry->mOffset = (S32)count;
+ mRequestId->mScopeEntry->mSize = 4;
+ count += mRequestId->mScopeEntry->mSize;
+
+ mStatus->mScopeEntry->mOffset = (S32)count;
+ mStatus->mScopeEntry->mSize = 4;
+ count += mStatus->mScopeEntry->mSize;
+
+ mMetadata->mScopeEntry->mOffset = (S32)count;
+ mMetadata->mScopeEntry->mSize = 4;
+ count += mMetadata->mScopeEntry->mSize;
+
+ mBody->mScopeEntry->mOffset = (S32)count;
+ mBody->mScopeEntry->mSize = 4;
+ count += mBody->mScopeEntry->mSize;
+ }
+ }
+ break;
+
+ case LSCP_EMIT_BYTE_CODE:
+ {
+#ifdef LSL_INCLUDE_DEBUG_INFO
+ char name[] = "http_response";
+ chunk->addBytes(name, strlen(name) + 1);
+ chunk->addBytes(mRequestId->mName, strlen(mRequestId->mName) + 1);
+ chunk->addBytes(mStatus->mName, strlen(mStatus->mName) + 1);
+ chunk->addBytes(mMetadata->mName, strlen(mMetadata->mName) + 1);
+ chunk->addBytes(mBody->mName, strlen(mBody->mName) + 1);
+#endif
+ }
+ break;
+
+ default:
+ mRequestId->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mStatus->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mMetadata->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mBody->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ break;
+ }
+}
+
+S32 LLScriptHTTPResponseEvent::getSize()
+{
+ // key + integer + list + string = 16
+ return 16;
+}
+
+
+void LLScriptMoneyEvent::recurse(FILE *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)
+{
+ if (gErrorToText.getErrors())
+ {
+ return;
+ }
+ switch(pass)
+ {
+ case LSCP_PRETTY_PRINT:
+ case LSCP_EMIT_ASSEMBLY:
+ fdotabs(fp, tabs, tabsize);
+ fprintf(fp, "money( key ");
+ mName->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, ", integer ");
+ mAmount->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, " )\n");
+ break;
+ case LSCP_SCOPE_PASS1:
+ if (scope->checkEntry(mName->mName))
+ {
+ gErrorToText.writeError(fp, this, LSERROR_DUPLICATE_NAME);
+ }
+ else
+ {
+ mName->mScopeEntry = scope->addEntry(mName->mName, LIT_VARIABLE, LST_KEY);
+ }
+ if (scope->checkEntry(mAmount->mName))
+ {
+ gErrorToText.writeError(fp, this, LSERROR_DUPLICATE_NAME);
+ }
+ else
+ {
+ mAmount->mScopeEntry = scope->addEntry(mAmount->mName, LIT_VARIABLE, LST_INTEGER);
+ }
+ break;
+ case LSCP_RESOURCE:
+ {
+ // we're just tryng to determine how much space the variable needs
+ if (mName->mScopeEntry)
+ {
+ mName->mScopeEntry->mOffset = (S32)count;
+ mName->mScopeEntry->mSize = 4;
+ count += mName->mScopeEntry->mSize;
+ mAmount->mScopeEntry->mOffset = (S32)count;
+ mAmount->mScopeEntry->mSize = 4;
+ count += mAmount->mScopeEntry->mSize;
+ }
+ }
+ break;
+ case LSCP_EMIT_BYTE_CODE:
+ {
+#ifdef LSL_INCLUDE_DEBUG_INFO
+ char name[] = "money";
+ chunk->addBytes(name, strlen(name) + 1);
+ chunk->addBytes(mName->mName, strlen(mName->mName) + 1);
+ chunk->addBytes(mAmount->mName, strlen(mAmount->mName) + 1);
+#endif
+ }
+ break;
+ default:
+ mName->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mAmount->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ break;
+ }
+}
+
+S32 LLScriptMoneyEvent::getSize()
+{
+ // key + integer = 8
+ return 8;
+}
+
+void LLScriptEmailEvent::recurse(FILE *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)
+{
+ if (gErrorToText.getErrors())
+ {
+ return;
+ }
+ switch(pass)
+ {
+ case LSCP_PRETTY_PRINT:
+ case LSCP_EMIT_ASSEMBLY:
+ fdotabs(fp, tabs, tabsize);
+ fprintf(fp, "email( string ");
+ mTime->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, ", string ");
+ mAddress->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, ", string ");
+ mSubject->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, ", string ");
+ mBody->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, ", integer ");
+ mNumber->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, " )\n");
+ break;
+ case LSCP_SCOPE_PASS1:
+ if (scope->checkEntry(mTime->mName))
+ {
+ gErrorToText.writeError(fp, this, LSERROR_DUPLICATE_NAME);
+ }
+ else
+ {
+ mTime->mScopeEntry = scope->addEntry(mTime->mName, LIT_VARIABLE, LST_STRING);
+ }
+ if (scope->checkEntry(mAddress->mName))
+ {
+ gErrorToText.writeError(fp, this, LSERROR_DUPLICATE_NAME);
+ }
+ else
+ {
+ mAddress->mScopeEntry = scope->addEntry(mAddress->mName, LIT_VARIABLE, LST_STRING);
+ }
+ if (scope->checkEntry(mSubject->mName))
+ {
+ gErrorToText.writeError(fp, this, LSERROR_DUPLICATE_NAME);
+ }
+ else
+ {
+ mSubject->mScopeEntry = scope->addEntry(mSubject->mName, LIT_VARIABLE, LST_STRING);
+ }
+ if (scope->checkEntry(mBody->mName))
+ {
+ gErrorToText.writeError(fp, this, LSERROR_DUPLICATE_NAME);
+ }
+ else
+ {
+ mBody->mScopeEntry = scope->addEntry(mBody->mName, LIT_VARIABLE, LST_STRING);
+ }
+ if (scope->checkEntry(mNumber->mName))
+ {
+ gErrorToText.writeError(fp, this, LSERROR_DUPLICATE_NAME);
+ }
+ else
+ {
+ mNumber->mScopeEntry = scope->addEntry(mNumber->mName, LIT_VARIABLE, LST_INTEGER);
+ }
+ break;
+ case LSCP_RESOURCE:
+ {
+ // we're just tryng to determine how much space the variable needs
+ if (mAddress->mScopeEntry)
+ {
+ mTime->mScopeEntry->mOffset = (S32)count;
+ mTime->mScopeEntry->mSize = 4;
+ count += mTime->mScopeEntry->mSize;
+ mAddress->mScopeEntry->mOffset = (S32)count;
+ mAddress->mScopeEntry->mSize = 4;
+ count += mAddress->mScopeEntry->mSize;
+ mSubject->mScopeEntry->mOffset = (S32)count;
+ mSubject->mScopeEntry->mSize = 4;
+ count += mSubject->mScopeEntry->mSize;
+ mBody->mScopeEntry->mOffset = (S32)count;
+ mBody->mScopeEntry->mSize = 4;
+ count += mBody->mScopeEntry->mSize;
+ mNumber->mScopeEntry->mOffset = (S32)count;
+ mNumber->mScopeEntry->mSize = 4;
+ count += mNumber->mScopeEntry->mSize;
+ }
+ }
+ break;
+ case LSCP_EMIT_BYTE_CODE:
+ {
+#ifdef LSL_INCLUDE_DEBUG_INFO
+ char name[] = "email";
+ chunk->addBytes(name, strlen(name) + 1);
+ chunk->addBytes(mTime->mName, strlen(mTime->mName) + 1);
+ chunk->addBytes(mAddress->mName, strlen(mAddress->mName) + 1);
+ chunk->addBytes(mSubject->mName, strlen(mSubject->mName) + 1);
+ chunk->addBytes(mBody->mName, strlen(mBody->mName) + 1);
+ chunk->addBytes(mNumber->mName, strlen(mNumber->mName) + 1);
+#endif
+ }
+ break;
+ default:
+ mTime->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mAddress->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mSubject->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mBody->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mNumber->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ break;
+ }
+}
+
+S32 LLScriptEmailEvent::getSize()
+{
+ // string + string + string + string + integer = 16
+ return 20;
+}
+
+void LLScriptRezEvent::recurse(FILE *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)
+{
+ if (gErrorToText.getErrors())
+ {
+ return;
+ }
+ switch(pass)
+ {
+ case LSCP_PRETTY_PRINT:
+ case LSCP_EMIT_ASSEMBLY:
+ fdotabs(fp, tabs, tabsize);
+ fprintf(fp, "rez( integer ");
+ mStartParam->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, " )\n");
+ break;
+ case LSCP_SCOPE_PASS1:
+ if (scope->checkEntry(mStartParam->mName))
+ {
+ gErrorToText.writeError(fp, this, LSERROR_DUPLICATE_NAME);
+ }
+ else
+ {
+ mStartParam->mScopeEntry = scope->addEntry(mStartParam->mName, LIT_VARIABLE, LST_INTEGER);
+ }
+ break;
+ case LSCP_RESOURCE:
+ {
+ // we're just tryng to determine how much space the variable needs
+ if (mStartParam->mScopeEntry)
+ {
+ mStartParam->mScopeEntry->mOffset = (S32)count;
+ mStartParam->mScopeEntry->mSize = 4;
+ count += mStartParam->mScopeEntry->mSize;
+ }
+ }
+ break;
+ case LSCP_EMIT_BYTE_CODE:
+ {
+#ifdef LSL_INCLUDE_DEBUG_INFO
+ char name[] = "rez";
+ chunk->addBytes(name, strlen(name) + 1);
+ chunk->addBytes(mStartParam->mName, strlen(mStartParam->mName) + 1);
+#endif
+ }
+ break;
+ default:
+ mStartParam->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ break;
+ }
+}
+
+S32 LLScriptRezEvent::getSize()
+{
+ // integer = 4
+ return 4;
+}
+
+void LLScriptNoSensorEvent::recurse(FILE *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)
+{
+ if (gErrorToText.getErrors())
+ {
+ return;
+ }
+ switch(pass)
+ {
+ case LSCP_PRETTY_PRINT:
+ fdotabs(fp, tabs, tabsize);
+ fprintf(fp, "no_sensor()\n");
+ break;
+ case LSCP_EMIT_ASSEMBLY:
+ fprintf(fp, "no_sensor()\n");
+ break;
+ case LSCP_EMIT_BYTE_CODE:
+ {
+#ifdef LSL_INCLUDE_DEBUG_INFO
+ char name[] = "no_sensor";
+ chunk->addBytes(name, strlen(name) + 1);
+#endif
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+S32 LLScriptNoSensorEvent::getSize()
+{
+ return 0;
+}
+
+void LLScriptAtTarget::recurse(FILE *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)
+{
+ if (gErrorToText.getErrors())
+ {
+ return;
+ }
+ switch(pass)
+ {
+ case LSCP_PRETTY_PRINT:
+ case LSCP_EMIT_ASSEMBLY:
+ fdotabs(fp, tabs, tabsize);
+ fprintf(fp, "at_target( integer ");
+ mTargetNumber->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, ", vector ");
+ mTargetPosition->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, ", vector ");
+ mOurPosition->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, " )\n");
+ break;
+ case LSCP_SCOPE_PASS1:
+ if (scope->checkEntry(mTargetNumber->mName))
+ {
+ gErrorToText.writeError(fp, this, LSERROR_DUPLICATE_NAME);
+ }
+ else
+ {
+ mTargetNumber->mScopeEntry = scope->addEntry(mTargetNumber->mName, LIT_VARIABLE, LST_INTEGER);
+ }
+ if (scope->checkEntry(mTargetPosition->mName))
+ {
+ gErrorToText.writeError(fp, this, LSERROR_DUPLICATE_NAME);
+ }
+ else
+ {
+ mTargetPosition->mScopeEntry = scope->addEntry(mTargetPosition->mName, LIT_VARIABLE, LST_VECTOR);
+ }
+ if (scope->checkEntry(mOurPosition->mName))
+ {
+ gErrorToText.writeError(fp, this, LSERROR_DUPLICATE_NAME);
+ }
+ else
+ {
+ mOurPosition->mScopeEntry = scope->addEntry(mOurPosition->mName, LIT_VARIABLE, LST_VECTOR);
+ }
+ break;
+ case LSCP_RESOURCE:
+ {
+ // we're just tryng to determine how much space the variable needs
+ if (mTargetNumber->mScopeEntry)
+ {
+ mTargetNumber->mScopeEntry->mOffset = (S32)count;
+ mTargetNumber->mScopeEntry->mSize = 4;
+ count += mTargetNumber->mScopeEntry->mSize;
+ mTargetPosition->mScopeEntry->mOffset = (S32)count;
+ mTargetPosition->mScopeEntry->mSize = 12;
+ count += mTargetPosition->mScopeEntry->mSize;
+ mOurPosition->mScopeEntry->mOffset = (S32)count;
+ mOurPosition->mScopeEntry->mSize = 12;
+ count += mOurPosition->mScopeEntry->mSize;
+ }
+ }
+ break;
+ case LSCP_EMIT_BYTE_CODE:
+ {
+#ifdef LSL_INCLUDE_DEBUG_INFO
+ char name[] = "at_target";
+ chunk->addBytes(name, strlen(name) + 1);
+ chunk->addBytes(mTargetNumber->mName, strlen(mTargetNumber->mName) + 1);
+ chunk->addBytes(mTargetPosition->mName, strlen(mTargetPosition->mName) + 1);
+ chunk->addBytes(mOurPosition->mName, strlen(mOurPosition->mName) + 1);
+#endif
+ }
+ break;
+ default:
+ mTargetNumber->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mTargetPosition->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mOurPosition->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ break;
+ }
+}
+
+S32 LLScriptAtTarget::getSize()
+{
+ // integer + vector + vector = 28
+ return 28;
+}
+
+
+
+void LLScriptNotAtTarget::recurse(FILE *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)
+{
+ if (gErrorToText.getErrors())
+ {
+ return;
+ }
+ switch(pass)
+ {
+ case LSCP_PRETTY_PRINT:
+ fdotabs(fp, tabs, tabsize);
+ fprintf(fp, "not_at_target()\n");
+ break;
+ case LSCP_EMIT_ASSEMBLY:
+ fprintf(fp, "not_at_target()\n");
+ break;
+ case LSCP_EMIT_BYTE_CODE:
+ {
+#ifdef LSL_INCLUDE_DEBUG_INFO
+ char name[] = "not_at_target";
+ chunk->addBytes(name, strlen(name) + 1);
+#endif
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+S32 LLScriptNotAtTarget::getSize()
+{
+ return 0;
+}
+
+void LLScriptAtRotTarget::recurse(FILE *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)
+{
+ if (gErrorToText.getErrors())
+ {
+ return;
+ }
+ switch(pass)
+ {
+ case LSCP_PRETTY_PRINT:
+ case LSCP_EMIT_ASSEMBLY:
+ fdotabs(fp, tabs, tabsize);
+ fprintf(fp, "at_target( integer ");
+ mTargetNumber->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, ", quaternion ");
+ mTargetRotation->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, ", quaternion ");
+ mOurRotation->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, " )\n");
+ break;
+ case LSCP_SCOPE_PASS1:
+ if (scope->checkEntry(mTargetNumber->mName))
+ {
+ gErrorToText.writeError(fp, this, LSERROR_DUPLICATE_NAME);
+ }
+ else
+ {
+ mTargetNumber->mScopeEntry = scope->addEntry(mTargetNumber->mName, LIT_VARIABLE, LST_INTEGER);
+ }
+ if (scope->checkEntry(mTargetRotation->mName))
+ {
+ gErrorToText.writeError(fp, this, LSERROR_DUPLICATE_NAME);
+ }
+ else
+ {
+ mTargetRotation->mScopeEntry = scope->addEntry(mTargetRotation->mName, LIT_VARIABLE, LST_QUATERNION);
+ }
+ if (scope->checkEntry(mOurRotation->mName))
+ {
+ gErrorToText.writeError(fp, this, LSERROR_DUPLICATE_NAME);
+ }
+ else
+ {
+ mOurRotation->mScopeEntry = scope->addEntry(mOurRotation->mName, LIT_VARIABLE, LST_QUATERNION);
+ }
+ break;
+ case LSCP_RESOURCE:
+ {
+ // we're just tryng to determine how much space the variable needs
+ if (mTargetNumber->mScopeEntry)
+ {
+ mTargetNumber->mScopeEntry->mOffset = (S32)count;
+ mTargetNumber->mScopeEntry->mSize = 4;
+ count += mTargetNumber->mScopeEntry->mSize;
+ mTargetRotation->mScopeEntry->mOffset = (S32)count;
+ mTargetRotation->mScopeEntry->mSize = 16;
+ count += mTargetRotation->mScopeEntry->mSize;
+ mOurRotation->mScopeEntry->mOffset = (S32)count;
+ mOurRotation->mScopeEntry->mSize = 16;
+ count += mOurRotation->mScopeEntry->mSize;
+ }
+ }
+ break;
+ case LSCP_EMIT_BYTE_CODE:
+ {
+#ifdef LSL_INCLUDE_DEBUG_INFO
+ char name[] = "at_rot_target";
+ chunk->addBytes(name, strlen(name) + 1);
+ chunk->addBytes(mTargetNumber->mName, strlen(mTargetNumber->mName) + 1);
+ chunk->addBytes(mTargetRotation->mName, strlen(mTargetRotation->mName) + 1);
+ chunk->addBytes(mOurRotation->mName, strlen(mOurRotation->mName) + 1);
+#endif
+ }
+ break;
+ default:
+ mTargetNumber->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mTargetRotation->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mOurRotation->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ break;
+ }
+}
+
+S32 LLScriptAtRotTarget::getSize()
+{
+ // integer + quaternion + quaternion = 36
+ return 36;
+}
+
+
+
+void LLScriptNotAtRotTarget::recurse(FILE *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)
+{
+ if (gErrorToText.getErrors())
+ {
+ return;
+ }
+ switch(pass)
+ {
+ case LSCP_PRETTY_PRINT:
+ fdotabs(fp, tabs, tabsize);
+ fprintf(fp, "not_at_rot_target()\n");
+ break;
+ case LSCP_EMIT_ASSEMBLY:
+ fprintf(fp, "not_at_rot_target()\n");
+ break;
+ case LSCP_EMIT_BYTE_CODE:
+ {
+#ifdef LSL_INCLUDE_DEBUG_INFO
+ char name[] = "not_at_rot_target";
+ chunk->addBytes(name, strlen(name) + 1);
+#endif
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+S32 LLScriptNotAtRotTarget::getSize()
+{
+ return 0;
+}
+
+
+
+void LLScriptExpression::addExpression(LLScriptExpression *expression)
+{
+ if (mNextp)
+ {
+ expression->mNextp = mNextp;
+ }
+ mNextp = expression;
+}
+
+void LLScriptExpression::recurse(FILE *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)
+{
+ fprintf(fp, "Expression Base Class -- should never get here!\n");
+}
+
+S32 LLScriptExpression::getSize()
+{
+ printf("Expression Base Class -- should never get here!\n");
+ return 0;
+}
+
+void LLScriptExpression::gonext(FILE *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)
+{
+ if (gErrorToText.getErrors())
+ {
+ return;
+ }
+ switch(pass)
+ {
+ case LSCP_PRETTY_PRINT:
+ if (mNextp)
+ {
+ fprintf(fp, ", ");
+ mNextp->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ }
+ break;
+ default:
+ if (mNextp)
+ {
+ mNextp->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ }
+ break;
+ }
+}
+
+void LLScriptForExpressionList::recurse(FILE *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)
+{
+ if (gErrorToText.getErrors())
+ {
+ return;
+ }
+ switch(pass)
+ {
+ case LSCP_PRETTY_PRINT:
+ mFirstp->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ if (mSecondp)
+ {
+ fprintf(fp, ", ");
+ mSecondp->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ }
+ break;
+ case LSCP_EMIT_ASSEMBLY:
+ mFirstp->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ if (mFirstp->mReturnType)
+ {
+ fprintf(fp, "%s\n", LSCRIPTTypePop[mFirstp->mReturnType]);
+ }
+ if (mSecondp)
+ {
+ mSecondp->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ if (mSecondp->mReturnType)
+ {
+ fprintf(fp, "%s\n", LSCRIPTTypePop[mSecondp->mReturnType]);
+ }
+ }
+ break;
+ case LSCP_TO_STACK:
+ mFirstp->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ switch(mFirstp->mReturnType)
+ {
+ case LST_INTEGER:
+ case LST_FLOATINGPOINT:
+ chunk->addByte(LSCRIPTOpCodes[LOPC_POP]);
+ break;
+ case LST_STRING:
+ case LST_KEY:
+ chunk->addByte(LSCRIPTOpCodes[LOPC_POPS]);
+ break;
+ case LST_LIST:
+ chunk->addByte(LSCRIPTOpCodes[LOPC_POPL]);
+ break;
+ case LST_VECTOR:
+ chunk->addByte(LSCRIPTOpCodes[LOPC_POPV]);
+ break;
+ case LST_QUATERNION:
+ chunk->addByte(LSCRIPTOpCodes[LOPC_POPQ]);
+ break;
+ default:
+ break;
+ }
+ if (mSecondp)
+ {
+ mSecondp->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ switch(mSecondp->mReturnType)
+ {
+ case LST_INTEGER:
+ case LST_FLOATINGPOINT:
+ chunk->addByte(LSCRIPTOpCodes[LOPC_POP]);
+ break;
+ case LST_STRING:
+ case LST_KEY:
+ chunk->addByte(LSCRIPTOpCodes[LOPC_POPS]);
+ break;
+ case LST_LIST:
+ chunk->addByte(LSCRIPTOpCodes[LOPC_POPL]);
+ break;
+ case LST_VECTOR:
+ chunk->addByte(LSCRIPTOpCodes[LOPC_POPV]);
+ break;
+ case LST_QUATERNION:
+ chunk->addByte(LSCRIPTOpCodes[LOPC_POPQ]);
+ break;
+ default:
+ break;
+ }
+ }
+ break;
+ case LSCP_EMIT_CIL_ASSEMBLY:
+ mFirstp->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ if (mFirstp->mReturnType)
+ {
+ fprintf(fp, "pop\n");
+ }
+ if (mSecondp)
+ {
+ mSecondp->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ if (mSecondp->mReturnType)
+ {
+ fprintf(fp, "pop\n");
+ }
+ }
+ break;
+ default:
+ mFirstp->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ if (mSecondp)
+ {
+ mSecondp->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ }
+ break;
+ }
+}
+
+S32 LLScriptForExpressionList::getSize()
+{
+ return 0;
+}
+
+void LLScriptFuncExpressionList::recurse(FILE *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)
+{
+ if (gErrorToText.getErrors())
+ {
+ return;
+ }
+ switch(pass)
+ {
+ case LSCP_PRETTY_PRINT:
+ mFirstp->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ if (mSecondp)
+ {
+ fprintf(fp, ", ");
+ mSecondp->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ }
+ break;
+ case LSCP_TYPE:
+ {
+ mFirstp->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ if (!entry->mFunctionArgs.getType(entrycount))
+ {
+ gErrorToText.writeError(fp, this, LSERROR_FUNCTION_TYPE_ERROR);
+ }
+ if (!legal_assignment(entry->mFunctionArgs.getType(entrycount), mFirstp->mReturnType))
+ {
+ gErrorToText.writeError(fp, this, LSERROR_FUNCTION_TYPE_ERROR);
+ }
+ count++;
+ entrycount++;
+ if (mSecondp)
+ {
+ mSecondp->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ if (mSecondp->mReturnType)
+ {
+ count++;
+ if (!entry->mFunctionArgs.getType(entrycount))
+ {
+ gErrorToText.writeError(fp, this, LSERROR_FUNCTION_TYPE_ERROR);
+ }
+ if (!legal_assignment(entry->mFunctionArgs.getType(entrycount), mSecondp->mReturnType))
+ {
+ gErrorToText.writeError(fp, this, LSERROR_FUNCTION_TYPE_ERROR);
+ }
+ }
+ }
+ }
+ break;
+ case LSCP_EMIT_ASSEMBLY:
+ {
+ mFirstp->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ LSCRIPTType argtype = entry->mFunctionArgs.getType(entrycount);
+ if (argtype != mFirstp->mReturnType)
+ {
+ fprintf(fp, "CAST %s->%s\n", LSCRIPTTypeNames[mFirstp->mReturnType], LSCRIPTTypeNames[argtype]);
+ }
+ entrycount++;
+ if (mSecondp)
+ {
+ mSecondp->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ if (mSecondp->mReturnType)
+ {
+ argtype = entry->mFunctionArgs.getType(entrycount);
+ if (argtype != mSecondp->mReturnType)
+ {
+ fprintf(fp, "CAST %s->%s\n", LSCRIPTTypeNames[mSecondp->mReturnType], LSCRIPTTypeNames[argtype]);
+ }
+ }
+ }
+ }
+ break;
+ case LSCP_TO_STACK:
+ {
+ mFirstp->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ LSCRIPTType argtype = entry->mFunctionArgs.getType(entrycount);
+ if (argtype != mFirstp->mReturnType)
+ {
+ chunk->addByte(LSCRIPTOpCodes[LOPC_CAST]);
+ U8 castbyte = LSCRIPTTypeByte[argtype] | LSCRIPTTypeHi4Bits[mFirstp->mReturnType];
+ chunk->addByte(castbyte);
+ }
+ entrycount++;
+ if (mSecondp)
+ {
+ mSecondp->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ if (mSecondp->mReturnType)
+ {
+ argtype = entry->mFunctionArgs.getType(entrycount);
+ if (argtype != mSecondp->mReturnType)
+ {
+ chunk->addByte(LSCRIPTOpCodes[LOPC_CAST]);
+ U8 castbyte = LSCRIPTTypeByte[argtype] | LSCRIPTTypeHi4Bits[mSecondp->mReturnType];
+ chunk->addByte(castbyte);
+ }
+ }
+ }
+ }
+ break;
+ /* TODO: Fix conflict between global/local variable determination needing caller scope and cast determination here needs callee scope...
+ case LSCP_EMIT_CIL_ASSEMBLY:
+ {
+ mFirstp->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ LSCRIPTType argtype = entry->mFunctionArgs.getType(entrycount);
+ if (argtype != mFirstp->mReturnType)
+ {
+ print_cil_cast(fp, mFirstp->mReturnType, argtype);
+ }
+ entrycount++;
+ if (mSecondp)
+ {
+ mSecondp->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ if (mSecondp->mReturnType)
+ {
+ argtype = entry->mFunctionArgs.getType(entrycount);
+ if (argtype != mSecondp->mReturnType)
+ {
+ print_cil_cast(fp, mFirstp->mReturnType, argtype);
+ }
+ }
+ }
+ }
+ break;
+ */
+ default:
+ mFirstp->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ if (mSecondp)
+ {
+ mSecondp->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ }
+ break;
+ }
+}
+
+S32 LLScriptFuncExpressionList::getSize()
+{
+ return 0;
+}
+
+void LLScriptListExpressionList::recurse(FILE *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)
+{
+ if (gErrorToText.getErrors())
+ {
+ return;
+ }
+ switch(pass)
+ {
+ case LSCP_PRETTY_PRINT:
+ mFirstp->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ if (mSecondp)
+ {
+ fprintf(fp, ", ");
+ mSecondp->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ }
+ break;
+ case LSCP_EMIT_ASSEMBLY:
+ mFirstp->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ if (mFirstp->mType != LET_LIST_EXPRESSION_LIST)
+ {
+ fprintf(fp, "%s\n", LSCRIPTListDescription[mFirstp->mReturnType]);
+ count++;
+ }
+ if (mSecondp)
+ {
+ mSecondp->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ if (mSecondp->mType != LET_LIST_EXPRESSION_LIST)
+ {
+ fprintf(fp, "%s\n", LSCRIPTListDescription[mSecondp->mReturnType]);
+ count++;
+ }
+ }
+ break;
+ case LSCP_TO_STACK:
+ mFirstp->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ if (mFirstp->mType != LET_LIST_EXPRESSION_LIST)
+ {
+ chunk->addByte(LSCRIPTOpCodes[LOPC_PUSHARGB]);
+ chunk->addByte(LSCRIPTTypeByte[mFirstp->mReturnType]);
+ count++;
+ }
+ if (mSecondp)
+ {
+ mSecondp->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ if (mSecondp->mType != LET_LIST_EXPRESSION_LIST)
+ {
+ chunk->addByte(LSCRIPTOpCodes[LOPC_PUSHARGB]);
+ chunk->addByte(LSCRIPTTypeByte[mSecondp->mReturnType]);
+ count++;
+ }
+ }
+ break;
+ case LSCP_EMIT_CIL_ASSEMBLY:
+ // Evaluate expressions in reverse order so first expression is on top of stack.
+ // Results can then be popped and appended to list to result in list with correct order.
+ if (mSecondp)
+ {
+ mSecondp->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ if (mSecondp->mType != LET_LIST_EXPRESSION_LIST)
+ {
+ // Box value.
+ print_cil_box(fp, mSecondp->mReturnType);
+
+ ++count;
+ }
+ }
+ mFirstp->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ if (mFirstp->mType != LET_LIST_EXPRESSION_LIST)
+ {
+ // Box value.
+ print_cil_box(fp, mFirstp->mReturnType);
+
+ ++count;
+ }
+ break;
+ default:
+ mFirstp->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ if (mSecondp)
+ {
+ mSecondp->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ }
+ break;
+ }
+}
+
+S32 LLScriptListExpressionList::getSize()
+{
+ return 0;
+}
+
+// Returns true if identifier is a parameter and false if identifier is a local variable within function_scope.
+bool is_parameter(LLScriptIdentifier* identifier, LLScriptScopeEntry* function_scope)
+{
+ // Function offset stores offset of first local.
+ // Compare variable offset with function offset to
+ // determine whether variable is local or parameter.
+ return (identifier->mScopeEntry->mOffset < function_scope->mOffset);
+}
+
+// If assignment is to global variable, pushes this pointer on to stack.
+void print_cil_load_address(FILE* fp, LLScriptExpression* exp, LLScriptScopeEntry* function_scope)
+{
+ LLScriptLValue *lvalue = (LLScriptLValue *) exp;
+ LLScriptIdentifier *ident = lvalue->mIdentifier;
+
+ // If global (member), load this pointer.
+ if(ident->mScopeEntry->mIDType == LIT_GLOBAL)
+ {
+ fprintf(fp, "ldarg.0\n");
+ }
+
+ // If accessor, load address of object.
+ if(lvalue->mAccessor)
+ {
+ if(ident->mScopeEntry->mIDType == LIT_VARIABLE)
+ {
+ if(is_parameter(ident, function_scope))
+ {
+ // Parameter, load by name.
+ fprintf(fp, "ldarga.s %s\n", ident->mScopeEntry->mIdentifier);
+ }
+ else
+ {
+ // Local, load by index.
+ fprintf(fp, "ldloca.s %d\n", ident->mScopeEntry->mCount);
+ }
+ }
+ else if (ident->mScopeEntry->mIDType == LIT_GLOBAL)
+ {
+ fprintf(fp, "ldflda ");
+ print_cil_type(fp, ident->mScopeEntry->mType);
+ fprintf(fp, " LSL::%s\n", ident->mScopeEntry->mIdentifier);
+ }
+ }
+}
+
+void print_cil_accessor(FILE* fp, LLScriptLValue *lvalue)
+{
+ LLScriptIdentifier *ident = lvalue->mIdentifier;
+ print_cil_type(fp, lvalue->mReturnType);
+ fprintf(fp, " ");
+ print_cil_type(fp, ident->mScopeEntry->mType);
+ fprintf(fp, "::%s\n", lvalue->mAccessor->mName);
+}
+
+void print_cil_member(FILE* fp, LLScriptIdentifier *ident)
+{
+ print_cil_type(fp, ident->mScopeEntry->mType);
+ fprintf(fp, " LSL::%s\n", ident->mScopeEntry->mIdentifier);
+}
+
+void LLScriptLValue::recurse(FILE *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)
+{
+ if (gErrorToText.getErrors())
+ {
+ return;
+ }
+ switch(pass)
+ {
+ case LSCP_PRETTY_PRINT:
+ mIdentifier->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ if (mAccessor)
+ {
+ fprintf(fp, ".");
+ mAccessor->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ }
+ break;
+ case LSCP_EMIT_ASSEMBLY:
+ if (mIdentifier->mScopeEntry->mIDType == LIT_VARIABLE)
+ {
+ if (mAccessor)
+ {
+ fprintf(fp, "%s%d [%s.%s]\n", LSCRIPTTypeLocalPush[mReturnType], mIdentifier->mScopeEntry->mOffset + mOffset, mIdentifier->mName, mAccessor->mName);
+ }
+ else
+ {
+ fprintf(fp, "%s%d [%s]\n", LSCRIPTTypeLocalPush[mIdentifier->mScopeEntry->mType], mIdentifier->mScopeEntry->mOffset, mIdentifier->mName);
+ }
+ }
+ else if (mIdentifier->mScopeEntry->mIDType == LIT_GLOBAL)
+ {
+ if (mAccessor)
+ {
+ fprintf(fp, "%s%d [%s.%s]\n", LSCRIPTTypeGlobalPush[mReturnType], mIdentifier->mScopeEntry->mOffset + mOffset, mIdentifier->mName, mAccessor->mName);
+ }
+ else
+ {
+ fprintf(fp, "%s%d [%s]\n", LSCRIPTTypeGlobalPush[mIdentifier->mScopeEntry->mType], mIdentifier->mScopeEntry->mOffset, mIdentifier->mName);
+ }
+ }
+ else
+ {
+ fprintf(fp, "Unexpected LValue!\n");
+ }
+ break;
+ case LSCP_SCOPE_PASS1:
+ {
+ LLScriptScopeEntry *entry = scope->findEntry(mIdentifier->mName);
+ if (!entry || ( (entry->mIDType != LIT_GLOBAL) && (entry->mIDType != LIT_VARIABLE)))
+ {
+ gErrorToText.writeError(fp, this, LSERROR_UNDEFINED_NAME);
+ }
+ else
+ {
+ // if we did find it, make sure this identifier is associated with the correct scope entry
+ mIdentifier->mScopeEntry = entry;
+ }
+ }
+ break;
+ case LSCP_TYPE:
+ // if we have an accessor, we need to change what type our identifier returns and set our offset value
+ if (mIdentifier->mScopeEntry)
+ {
+ if (mAccessor)
+ {
+ BOOL b_ok = FALSE;
+ if (mIdentifier->mScopeEntry->mIDType == LIT_VARIABLE)
+ {
+ if (mIdentifier->mScopeEntry->mType == LST_VECTOR)
+ {
+ if (!strcmp("x", mAccessor->mName))
+ {
+ mOffset = 0;
+ b_ok = TRUE;
+ }
+ else if (!strcmp("y", mAccessor->mName))
+ {
+ mOffset = 4;
+ b_ok = TRUE;
+ }
+ else if (!strcmp("z", mAccessor->mName))
+ {
+ mOffset = 8;
+ b_ok = TRUE;
+ }
+ }
+ else if (mIdentifier->mScopeEntry->mType == LST_QUATERNION)
+ {
+ if (!strcmp("x", mAccessor->mName))
+ {
+ mOffset = 0;
+ b_ok = TRUE;
+ }
+ else if (!strcmp("y", mAccessor->mName))
+ {
+ mOffset = 4;
+ b_ok = TRUE;
+ }
+ else if (!strcmp("z", mAccessor->mName))
+ {
+ mOffset = 8;
+ b_ok = TRUE;
+ }
+ else if (!strcmp("s", mAccessor->mName))
+ {
+ mOffset = 12;
+ b_ok = TRUE;
+ }
+ }
+ }
+ else
+ {
+ if (mIdentifier->mScopeEntry->mType == LST_VECTOR)
+ {
+ if (!strcmp("x", mAccessor->mName))
+ {
+ mOffset = 8;
+ b_ok = TRUE;
+ }
+ else if (!strcmp("y", mAccessor->mName))
+ {
+ mOffset = 4;
+ b_ok = TRUE;
+ }
+ else if (!strcmp("z", mAccessor->mName))
+ {
+ mOffset = 0;
+ b_ok = TRUE;
+ }
+ }
+ else if (mIdentifier->mScopeEntry->mType == LST_QUATERNION)
+ {
+ if (!strcmp("x", mAccessor->mName))
+ {
+ mOffset = 12;
+ b_ok = TRUE;
+ }
+ else if (!strcmp("y", mAccessor->mName))
+ {
+ mOffset = 8;
+ b_ok = TRUE;
+ }
+ else if (!strcmp("z", mAccessor->mName))
+ {
+ mOffset = 4;
+ b_ok = TRUE;
+ }
+ else if (!strcmp("s", mAccessor->mName))
+ {
+ mOffset = 0;
+ b_ok = TRUE;
+ }
+ }
+ }
+ if (b_ok)
+ {
+ mReturnType = type = LST_FLOATINGPOINT;
+ }
+ else
+ {
+ gErrorToText.writeError(fp, this, LSERROR_VECTOR_METHOD_ERROR);
+ }
+ }
+ else
+ {
+ mReturnType = type = mIdentifier->mScopeEntry->mType;
+ }
+ }
+ else
+ {
+ mReturnType = type = LST_UNDEFINED;
+ }
+ break;
+ case LSCP_TO_STACK:
+ {
+ switch(mReturnType)
+ {
+ case LST_INTEGER:
+ case LST_FLOATINGPOINT:
+ if (mIdentifier->mScopeEntry->mIDType == LIT_VARIABLE)
+ {
+ chunk->addByte(LSCRIPTOpCodes[LOPC_PUSH]);
+ }
+ else
+ {
+ chunk->addByte(LSCRIPTOpCodes[LOPC_PUSHG]);
+ }
+ break;
+ case LST_KEY:
+ case LST_STRING:
+ if (mIdentifier->mScopeEntry->mIDType == LIT_VARIABLE)
+ {
+ chunk->addByte(LSCRIPTOpCodes[LOPC_PUSHS]);
+ }
+ else
+ {
+ chunk->addByte(LSCRIPTOpCodes[LOPC_PUSHGS]);
+ }
+ break;
+ case LST_LIST:
+ if (mIdentifier->mScopeEntry->mIDType == LIT_VARIABLE)
+ {
+ chunk->addByte(LSCRIPTOpCodes[LOPC_PUSHL]);
+ }
+ else
+ {
+ chunk->addByte(LSCRIPTOpCodes[LOPC_PUSHGL]);
+ }
+ break;
+ case LST_VECTOR:
+ if (mIdentifier->mScopeEntry->mIDType == LIT_VARIABLE)
+ {
+ chunk->addByte(LSCRIPTOpCodes[LOPC_PUSHV]);
+ }
+ else
+ {
+ chunk->addByte(LSCRIPTOpCodes[LOPC_PUSHGV]);
+ }
+ break;
+ case LST_QUATERNION:
+ if (mIdentifier->mScopeEntry->mIDType == LIT_VARIABLE)
+ {
+ chunk->addByte(LSCRIPTOpCodes[LOPC_PUSHQ]);
+ }
+ else
+ {
+ chunk->addByte(LSCRIPTOpCodes[LOPC_PUSHGQ]);
+ }
+ break;
+ default:
+ if (mIdentifier->mScopeEntry->mIDType == LIT_VARIABLE)
+ {
+ chunk->addByte(LSCRIPTOpCodes[LOPC_PUSH]);
+ }
+ else
+ {
+ chunk->addByte(LSCRIPTOpCodes[LOPC_PUSHG]);
+ }
+ break;
+ }
+ S32 address = mIdentifier->mScopeEntry->mOffset + mOffset;
+ chunk->addInteger(address);
+ }
+ break;
+ case LSCP_EMIT_CIL_ASSEMBLY:
+ print_cil_load_address(fp, this, entry);
+ if(mAccessor)
+ {
+ fprintf(fp, "ldfld ");
+ print_cil_accessor(fp, this);
+ }
+ else if(mIdentifier->mScopeEntry->mIDType == LIT_VARIABLE)
+ {
+ if(is_parameter(mIdentifier, entry))
+ {
+ // Parameter, load by name.
+ fprintf(fp, "ldarg.s %s\n", mIdentifier->mScopeEntry->mIdentifier);
+ }
+ else
+ {
+ // Local, load by index.
+ fprintf(fp, "ldloc.s %d\n", mIdentifier->mScopeEntry->mCount);
+ }
+ }
+ else if (mIdentifier->mScopeEntry->mIDType == LIT_GLOBAL)
+ {
+ fprintf(fp, "ldfld ");
+ print_cil_member(fp, mIdentifier);
+ }
+ else
+ {
+ fprintf(fp, "Unexpected LValue!\n");
+ }
+ break;
+ default:
+ mIdentifier->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ break;
+ }
+ gonext(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+}
+
+S32 LLScriptLValue::getSize()
+{
+ return 0;
+}
+
+void print_asignment(FILE *fp, LLScriptExpression *exp)
+{
+ LLScriptLValue *lvalue = (LLScriptLValue *)exp;
+ LLScriptIdentifier *ident = lvalue->mIdentifier;
+ if (lvalue->mAccessor)
+ {
+ if (ident->mScopeEntry->mIDType == LIT_VARIABLE)
+ {
+ fprintf(fp, "%s%d [%s.%s]\n", LSCRIPTTypeLocalStore[ident->mScopeEntry->mType], ident->mScopeEntry->mOffset + lvalue->mOffset, ident->mName, lvalue->mAccessor->mName);
+ }
+ else if (ident->mScopeEntry->mIDType == LIT_GLOBAL)
+ {
+ fprintf(fp, "%s%d [%s.%s]\n", LSCRIPTTypeGlobalStore[ident->mScopeEntry->mType], ident->mScopeEntry->mOffset + lvalue->mOffset, ident->mName, lvalue->mAccessor->mName);
+ }
+ }
+ else
+ {
+ if (ident->mScopeEntry->mIDType == LIT_VARIABLE)
+ {
+ fprintf(fp, "%s%d [%s]\n", LSCRIPTTypeLocalStore[ident->mScopeEntry->mType], ident->mScopeEntry->mOffset, ident->mName);
+ }
+ else if (ident->mScopeEntry->mIDType == LIT_GLOBAL)
+ {
+ fprintf(fp, "%s%d [%s]\n", LSCRIPTTypeGlobalStore[ident->mScopeEntry->mType], ident->mScopeEntry->mOffset, ident->mName);
+ }
+ }
+}
+
+void print_cil_asignment(FILE *fp, LLScriptExpression *exp, LLScriptScopeEntry* function_scope)
+{
+ LLScriptLValue *lvalue = (LLScriptLValue *) exp;
+ LLScriptIdentifier *ident = lvalue->mIdentifier;
+ if (lvalue->mAccessor)
+ {
+ // Object address loaded, store in to field.
+ fprintf(fp, "stfld ");
+ print_cil_accessor(fp, lvalue);
+
+ // Load object address.
+ print_cil_load_address(fp, exp, function_scope);
+
+ // Load field.
+ fprintf(fp, "ldfld ");
+ print_cil_accessor(fp, lvalue);
+ }
+ else
+ {
+ if (ident->mScopeEntry->mIDType == LIT_VARIABLE)
+ {
+ // Language semantics require value of assignment to be left on stack.
+ // TODO: Optimise away redundant dup/pop pairs.
+ fprintf(fp, "dup\n");
+ if(is_parameter(ident, function_scope))
+ {
+ // Parameter, store by name.
+ fprintf(fp, "starg.s %s\n", ident->mScopeEntry->mIdentifier);
+ }
+ else
+ {
+ // Local, store by index.
+ fprintf(fp, "stloc.s %d\n", ident->mScopeEntry->mCount);
+ }
+ }
+ else if (ident->mScopeEntry->mIDType == LIT_GLOBAL)
+ {
+ // Object address loaded, store in to field.
+ fprintf(fp, "stfld ");
+ print_cil_member(fp, ident);
+
+ // Load object address.
+ print_cil_load_address(fp, exp, function_scope);
+
+ // Load field.
+ fprintf(fp, "ldfld ");
+ print_cil_member(fp, ident);
+ }
+ }
+}
+
+void print_cast(FILE *fp, LSCRIPTType ret_type, LSCRIPTType right_type)
+{
+ if (right_type != ret_type)
+ {
+ fprintf(fp, "CAST %s->%s\n", LSCRIPTTypeNames[right_type], LSCRIPTTypeNames[ret_type]);
+ }
+}
+
+void cast2stack(LLScriptByteCodeChunk *chunk, LSCRIPTType ret_type, LSCRIPTType right_type)
+{
+ if (right_type != ret_type)
+ {
+ chunk->addByte(LSCRIPTOpCodes[LOPC_CAST]);
+ U8 castbyte = LSCRIPTTypeByte[right_type] | LSCRIPTTypeHi4Bits[ret_type];
+ chunk->addByte(castbyte);
+ }
+}
+
+void operation2stack(LLScriptByteCodeChunk *chunk, LSCRIPTType ret_type, LSCRIPTType right_type)
+{
+ U8 typebyte = LSCRIPTTypeByte[right_type] | LSCRIPTTypeHi4Bits[ret_type];
+ chunk->addByte(typebyte);
+}
+
+void store2stack(LLScriptExpression *exp, LLScriptExpression *lv, LLScriptByteCodeChunk *chunk, LSCRIPTType right_type)
+{
+ LLScriptLValue *lvalue = (LLScriptLValue *)lv;
+ LLScriptIdentifier *ident = lvalue->mIdentifier;
+ LSCRIPTType rettype = exp->mReturnType;
+
+ if (exp->mRightType != LST_NULL)
+ {
+ if (legal_binary_expression(rettype, exp->mLeftType, exp->mRightType, exp->mType))
+ cast2stack(chunk, right_type, exp->mReturnType);
+ }
+ switch(exp->mReturnType)
+ {
+ case LST_INTEGER:
+ case LST_FLOATINGPOINT:
+ if (ident->mScopeEntry->mIDType == LIT_VARIABLE)
+ {
+ chunk->addByte(LSCRIPTOpCodes[LOPC_STORE]);
+ }
+ else
+ {
+ chunk->addByte(LSCRIPTOpCodes[LOPC_STOREG]);
+ }
+ break;
+ case LST_KEY:
+ case LST_STRING:
+ if (ident->mScopeEntry->mIDType == LIT_VARIABLE)
+ {
+ chunk->addByte(LSCRIPTOpCodes[LOPC_STORES]);
+ }
+ else
+ {
+ chunk->addByte(LSCRIPTOpCodes[LOPC_STOREGS]);
+ }
+ break;
+ case LST_LIST:
+ if (ident->mScopeEntry->mIDType == LIT_VARIABLE)
+ {
+ chunk->addByte(LSCRIPTOpCodes[LOPC_STOREL]);
+ }
+ else
+ {
+ chunk->addByte(LSCRIPTOpCodes[LOPC_STOREGL]);
+ }
+ break;
+ case LST_VECTOR:
+ if (ident->mScopeEntry->mIDType == LIT_VARIABLE)
+ {
+ chunk->addByte(LSCRIPTOpCodes[LOPC_STOREV]);
+ }
+ else
+ {
+ chunk->addByte(LSCRIPTOpCodes[LOPC_STOREGV]);
+ }
+ break;
+ case LST_QUATERNION:
+ if (ident->mScopeEntry->mIDType == LIT_VARIABLE)
+ {
+ chunk->addByte(LSCRIPTOpCodes[LOPC_STOREQ]);
+ }
+ else
+ {
+ chunk->addByte(LSCRIPTOpCodes[LOPC_STOREGQ]);
+ }
+ break;
+ default:
+ if (ident->mScopeEntry->mIDType == LIT_VARIABLE)
+ {
+ chunk->addByte(LSCRIPTOpCodes[LOPC_STORE]);
+ }
+ else
+ {
+ chunk->addByte(LSCRIPTOpCodes[LOPC_STOREG]);
+ }
+ break;
+ }
+ S32 address = ident->mScopeEntry->mOffset + lvalue->mOffset;
+ chunk->addInteger(address);
+}
+
+void print_cil_numeric_cast(FILE* fp, LSCRIPTType currentArg, LSCRIPTType otherArg)
+{
+ if((currentArg == LST_INTEGER) && (otherArg == LST_FLOATINGPOINT))
+ {
+ print_cil_cast(fp, LST_INTEGER, LST_FLOATINGPOINT);
+ }
+}
+
+void LLScriptAssignment::recurse(FILE *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)
+{
+ if (gErrorToText.getErrors())
+ {
+ return;
+ }
+ switch(pass)
+ {
+ case LSCP_PRETTY_PRINT:
+ mLValue->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, " = ");
+ mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ break;
+ case LSCP_EMIT_ASSEMBLY:
+ {
+ mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ print_cast(fp, mReturnType, mRightType);
+ print_asignment(fp, mLValue);
+ }
+ break;
+ case LSCP_TYPE:
+ {
+ mLValue->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mLeftType = type;
+ mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mRightType = type;
+ if (!legal_assignment(mLeftType, mRightType))
+ {
+ gErrorToText.writeError(fp, this, LSERROR_TYPE_MISMATCH);
+ }
+ type = mReturnType = mLeftType;
+ }
+ break;
+ case LSCP_TO_STACK:
+ {
+ mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ store2stack(this, mLValue, chunk, mRightType);
+ }
+ break;
+ case LSCP_EMIT_CIL_ASSEMBLY:
+ {
+ print_cil_load_address(fp, mLValue, entry);
+ mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ print_cil_numeric_cast(fp, mRightType, mReturnType);
+ print_cil_asignment(fp, mLValue, entry);
+ }
+ break;
+ default:
+ mLValue->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ break;
+ }
+ gonext(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+}
+
+S32 LLScriptAssignment::getSize()
+{
+ return 0;
+}
+
+void print_cil_add(FILE* fp, LSCRIPTType left_type, LSCRIPTType right_type)
+{
+ switch(left_type)
+ {
+ case LST_INTEGER:
+ case LST_FLOATINGPOINT:
+
+ // Numeric addition.
+ fprintf(fp, "add\n");
+ break;
+
+ case LST_STRING:
+ case LST_KEY:
+
+ // String concatenation.
+ fprintf(fp, "call string valuetype [mscorlib]System.String::Concat(string, string)");
+ break;
+
+ case LST_VECTOR:
+
+ // Vector addition.
+ // TODO: Inline (requires temporary variables, which must be identified in earlier pass).
+ fprintf(fp, "call valuetype [LScriptLibrary]LLVector valuetype [LScriptLibrary]LLVector::'add_vec'(valuetype [LScriptLibrary]LLVector, valuetype [LScriptLibrary]LLVector)\n");
+ break;
+
+ case LST_QUATERNION:
+
+ // Rotation addition.
+ // TODO: Inline (requires temporary variables, which must be identified in earlier pass).
+ fprintf(fp, "call valuetype [LScriptLibrary]LLQuaternion valuetype [LScriptLibrary]LLQuaternion::'add_quat'(valuetype [LScriptLibrary]LLQuaternion, valuetype [LScriptLibrary]LLQuaternion)\n");
+ break;
+
+ case LST_LIST:
+ print_cil_box(fp, right_type);
+ fprintf(fp, "call class [mscorlib]System.Collections.ArrayList class [LScriptLibrary]LScriptInternal::AddReturnList(class [mscorlib]System.Collections.ArrayList, object)\n");
+ break;
+
+ default:
+ break;
+ }
+}
+
+void LLScriptAddAssignment::recurse(FILE *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)
+{
+ if (gErrorToText.getErrors())
+ {
+ return;
+ }
+ switch(pass)
+ {
+ case LSCP_PRETTY_PRINT:
+ mLValue->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, " += ");
+ mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ break;
+ case LSCP_EMIT_ASSEMBLY:
+ {
+ mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mLValue->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, "ADD %s, %s\n", LSCRIPTTypeNames[mRightType], LSCRIPTTypeNames[mLeftType]);
+ print_asignment(fp, mLValue);
+ }
+ break;
+ case LSCP_TYPE:
+ {
+ mLValue->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mLeftType = type;
+ mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mRightType = type;
+ if (!legal_binary_expression(mReturnType, mLeftType, mRightType, mType))
+ {
+ gErrorToText.writeError(fp, this, LSERROR_TYPE_MISMATCH);
+ }
+ type = mReturnType;
+ }
+ break;
+ case LSCP_TO_STACK:
+ {
+ mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mLValue->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ chunk->addByte(LSCRIPTOpCodes[LOPC_ADD]);
+ operation2stack(chunk, mReturnType, mRightType);
+ store2stack(this, mLValue, chunk, mReturnType);
+ }
+ break;
+ case LSCP_EMIT_CIL_ASSEMBLY:
+ {
+ print_cil_load_address(fp, mLValue, entry);
+ mLValue->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ print_cil_numeric_cast(fp, mLValue->mReturnType, mRightSide->mReturnType);
+ mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ print_cil_numeric_cast(fp, mRightSide->mReturnType, mLValue->mReturnType);
+ print_cil_add(fp, mLValue->mReturnType, mRightSide->mReturnType);
+ print_cil_asignment(fp, mLValue, entry);
+ }
+ break;
+ default:
+ mLValue->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ break;
+ }
+ gonext(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+}
+
+S32 LLScriptAddAssignment::getSize()
+{
+ return 0;
+}
+
+void print_cil_sub(FILE* fp, LSCRIPTType left_type, LSCRIPTType right_type)
+{
+ switch(left_type)
+ {
+ case LST_INTEGER:
+ case LST_FLOATINGPOINT:
+
+ // Numeric subtraction.
+ fprintf(fp, "sub\n");
+ break;
+
+ case LST_VECTOR:
+
+ // Vector subtraction.
+ // TODO: Inline (requires temporary variables, which must be identified in earlier pass).
+ fprintf(fp, "call valuetype [LScriptLibrary]LLVector valuetype [LScriptLibrary]LLVector::'subtract_vec'(valuetype [LScriptLibrary]LLVector, valuetype [LScriptLibrary]LLVector)\n");
+ break;
+
+ case LST_QUATERNION:
+
+ // Rotation subtraction.
+ // TODO: Inline (requires temporary variables, which must be identified in earlier pass).
+ fprintf(fp, "call valuetype [LScriptLibrary]LLQuaternion valuetype [LScriptLibrary]LLQuaternion::'subtract_quat'(valuetype [LScriptLibrary]LLQuaternion, valuetype [LScriptLibrary]LLQuaternion)\n");
+ break;
+
+ default:
+
+ // Error.
+ break;
+ }
+}
+
+void LLScriptSubAssignment::recurse(FILE *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)
+{
+ if (gErrorToText.getErrors())
+ {
+ return;
+ }
+ switch(pass)
+ {
+ case LSCP_PRETTY_PRINT:
+ mLValue->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, " -= ");
+ mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ break;
+ case LSCP_EMIT_ASSEMBLY:
+ {
+ mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mLValue->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, "SUB %s, %s\n", LSCRIPTTypeNames[mRightType], LSCRIPTTypeNames[mLeftType]);
+ print_asignment(fp, mLValue);
+ }
+ break;
+ case LSCP_TYPE:
+ {
+ mLValue->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mLeftType = type;
+ mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mRightType = type;
+ if (!legal_binary_expression(mReturnType, mLeftType, mRightType, mType))
+ {
+ gErrorToText.writeError(fp, this, LSERROR_TYPE_MISMATCH);
+ }
+ type = mReturnType;
+ }
+ break;
+ case LSCP_TO_STACK:
+ {
+ mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mLValue->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ chunk->addByte(LSCRIPTOpCodes[LOPC_SUB]);
+ operation2stack(chunk, mReturnType, mRightType);
+ store2stack(this, mLValue, chunk, mReturnType);
+ }
+ break;
+ case LSCP_EMIT_CIL_ASSEMBLY:
+ {
+ print_cil_load_address(fp, mLValue, entry);
+ mLValue->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ print_cil_numeric_cast(fp, mLValue->mReturnType, mRightSide->mReturnType);
+ mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ print_cil_numeric_cast(fp, mRightSide->mReturnType, mLValue->mReturnType);
+ print_cil_sub(fp, mLValue->mReturnType, mRightSide->mReturnType);
+ print_cil_asignment(fp, mLValue, entry);
+ }
+ break;
+ default:
+ mLValue->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ break;
+ }
+ gonext(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+}
+
+S32 LLScriptSubAssignment::getSize()
+{
+ return 0;
+}
+
+void print_cil_mul(FILE* fp, LSCRIPTType left_type, LSCRIPTType right_type)
+{
+ switch(left_type)
+ {
+ case LST_INTEGER:
+ case LST_FLOATINGPOINT:
+
+ // Numeric multiplication.
+ fprintf(fp, "mul\n");
+ break;
+
+ case LST_VECTOR:
+
+ switch(right_type)
+ {
+ case LST_INTEGER:
+
+ print_cil_cast(fp, LST_INTEGER, LST_FLOATINGPOINT);
+
+ case LST_FLOATINGPOINT:
+
+ // Vector scaling.
+ fprintf(fp, "call valuetype [LScriptLibrary]LLVector valuetype [LScriptLibrary]LLVector::'multiply_float'(valuetype [LScriptLibrary]LLVector, float32)\n");
+ break;
+
+ case LST_VECTOR:
+
+ // Dot product.
+ fprintf(fp, "call float32 valuetype [LScriptLibrary]LLVector::'multiply_vec'(valuetype [LScriptLibrary]LLVector, valuetype [LScriptLibrary]LLVector)\n");
+ break;
+
+ case LST_QUATERNION:
+
+ // Vector rotation.
+ fprintf(fp, "call valuetype [LScriptLibrary]LLVector valuetype [LScriptLibrary]LLVector::'multiply_quat'(valuetype [LScriptLibrary]LLVector, valuetype [LScriptLibrary]LLQuaternion)\n");
+ break;
+
+ default:
+ break;
+ }
+ break;
+
+ case LST_QUATERNION:
+
+ // Rotation multiplication.
+ fprintf(fp, "call valuetype [LScriptLibrary]LLQuaternion valuetype [LScriptLibrary]LLQuaternion::'multiply_quat'(valuetype [LScriptLibrary]LLQuaternion, valuetype [LScriptLibrary]LLQuaternion)\n");
+ break;
+
+ default:
+
+ // Error.
+ break;
+ }
+}
+
+void LLScriptMulAssignment::recurse(FILE *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)
+{
+ if (gErrorToText.getErrors())
+ {
+ return;
+ }
+ switch(pass)
+ {
+ case LSCP_PRETTY_PRINT:
+ mLValue->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, " *= ");
+ mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ break;
+ case LSCP_EMIT_ASSEMBLY:
+ {
+ mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mLValue->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, "MUL %s, %s\n", LSCRIPTTypeNames[mRightType], LSCRIPTTypeNames[mLeftType]);
+ print_asignment(fp, mLValue);
+ }
+ break;
+ case LSCP_TYPE:
+ {
+ mLValue->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mLeftType = type;
+ mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mRightType = type;
+ if (!legal_binary_expression(mReturnType, mLeftType, mRightType, mType))
+ {
+ gErrorToText.writeError(fp, this, LSERROR_TYPE_MISMATCH);
+ }
+ type = mReturnType;
+ }
+ break;
+ case LSCP_TO_STACK:
+ {
+ mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mLValue->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ chunk->addByte(LSCRIPTOpCodes[LOPC_MUL]);
+ operation2stack(chunk, mReturnType, mRightType);
+ store2stack(this, mLValue, chunk, mReturnType);
+ }
+ break;
+ case LSCP_EMIT_CIL_ASSEMBLY:
+ {
+ print_cil_load_address(fp, mLValue, entry);
+ mLValue->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ print_cil_numeric_cast(fp, mLValue->mReturnType, mRightSide->mReturnType);
+ mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ print_cil_numeric_cast(fp, mRightSide->mReturnType, mLValue->mReturnType);
+ print_cil_mul(fp, mLValue->mReturnType, mRightSide->mReturnType);
+ print_cil_asignment(fp, mLValue, entry);
+ }
+ break;
+ default:
+ mLValue->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ break;
+ }
+ gonext(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+}
+
+S32 LLScriptMulAssignment::getSize()
+{
+ return 0;
+}
+
+void print_cil_div(FILE* fp, LSCRIPTType left_type, LSCRIPTType right_type)
+{
+ switch(left_type)
+ {
+ case LST_INTEGER:
+ case LST_FLOATINGPOINT:
+
+ // Numeric addition.
+ fprintf(fp, "div\n");
+ break;
+
+ case LST_VECTOR:
+
+ switch(right_type)
+ {
+ case LST_INTEGER:
+
+ print_cil_cast(fp, LST_INTEGER, LST_FLOATINGPOINT);
+
+ case LST_FLOATINGPOINT:
+
+ // Scale.
+ fprintf(fp, "call valuetype [LScriptLibrary]LLVector valuetype [LScriptLibrary]LLVector::'divide_float'(valuetype [LScriptLibrary]LLVector, float32)\n");
+ break;
+
+ case LST_QUATERNION:
+
+ // Inverse rotation.
+ fprintf(fp, "call valuetype [LScriptLibrary]LLVector valuetype [LScriptLibrary]LLVector::'divide_quat'(valuetype [LScriptLibrary]LLVector, valuetype [LScriptLibrary]LLQuaternion)\n");
+ break;
+
+ default:
+ break;
+ }
+ break;
+
+ case LST_QUATERNION:
+
+ fprintf(fp, "call valuetype [LScriptLibrary]LLQuaternion valuetype [LScriptLibrary]LLQuaternion::'divide_quat'(valuetype [LScriptLibrary]LLQuaternion, valuetype [LScriptLibrary]LLQuaternion)\n");
+ break;
+
+ default:
+
+ // Error.
+ break;
+ }
+}
+
+void LLScriptDivAssignment::recurse(FILE *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)
+{
+ if (gErrorToText.getErrors())
+ {
+ return;
+ }
+ switch(pass)
+ {
+ case LSCP_PRETTY_PRINT:
+ mLValue->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, " /= ");
+ mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ break;
+ case LSCP_EMIT_ASSEMBLY:
+ {
+ mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mLValue->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, "DIV %s, %s\n", LSCRIPTTypeNames[mRightType], LSCRIPTTypeNames[mLeftType]);
+ print_asignment(fp, mLValue);
+ }
+ break;
+ case LSCP_TYPE:
+ {
+ mLValue->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mLeftType = type;
+ mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mRightType = type;
+ if (!legal_binary_expression(mReturnType, mLeftType, mRightType, mType))
+ {
+ gErrorToText.writeError(fp, this, LSERROR_TYPE_MISMATCH);
+ }
+ type = mReturnType;
+ }
+ break;
+ case LSCP_TO_STACK:
+ {
+ mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mLValue->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ chunk->addByte(LSCRIPTOpCodes[LOPC_DIV]);
+ operation2stack(chunk, mReturnType, mRightType);
+ store2stack(this, mLValue, chunk, mReturnType);
+ }
+ break;
+ case LSCP_EMIT_CIL_ASSEMBLY:
+ {
+ print_cil_load_address(fp, mLValue, entry);
+ mLValue->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ print_cil_numeric_cast(fp, mLValue->mReturnType, mRightSide->mReturnType);
+ mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ print_cil_numeric_cast(fp, mRightSide->mReturnType, mLValue->mReturnType);
+ print_cil_div(fp, mLValue->mReturnType, mRightSide->mReturnType);
+ print_cil_asignment(fp, mLValue, entry);
+ }
+ break;
+ default:
+ mLValue->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ break;
+ }
+ gonext(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+}
+
+S32 LLScriptDivAssignment::getSize()
+{
+ return 0;
+}
+
+void print_cil_mod(FILE* fp, LSCRIPTType left_type, LSCRIPTType right_type)
+{
+ switch(left_type)
+ {
+ case LST_INTEGER:
+
+ // Numeric remainder.
+ fprintf(fp, "rem\n");
+ break;
+
+ case LST_VECTOR:
+
+ // Vector cross product.
+ fprintf(fp, "call valuetype [LScriptLibrary]LLVector valuetype [LScriptLibrary]LLVector::'mod_vec'(valuetype [LScriptLibrary]LLVector, valuetype [LScriptLibrary]LLVector)\n");
+ break;
+
+ default:
+
+ // Error.
+ break;
+ }
+}
+
+void LLScriptModAssignment::recurse(FILE *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)
+{
+ if (gErrorToText.getErrors())
+ {
+ return;
+ }
+ switch(pass)
+ {
+ case LSCP_PRETTY_PRINT:
+ mLValue->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, " %%= ");
+ mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ break;
+ case LSCP_EMIT_ASSEMBLY:
+ {
+ mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mLValue->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, "MOD %s, %s\n", LSCRIPTTypeNames[mRightType], LSCRIPTTypeNames[mLeftType]);
+ print_asignment(fp, mLValue);
+ }
+ break;
+ case LSCP_TYPE:
+ {
+ mLValue->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mLeftType = type;
+ mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mRightType = type;
+ if (!legal_binary_expression(mReturnType, mLeftType, mRightType, mType))
+ {
+ gErrorToText.writeError(fp, this, LSERROR_TYPE_MISMATCH);
+ }
+ type = mReturnType;
+ }
+ break;
+ case LSCP_TO_STACK:
+ {
+ mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mLValue->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ chunk->addByte(LSCRIPTOpCodes[LOPC_MOD]);
+ operation2stack(chunk, mReturnType, mRightType);
+ store2stack(this, mLValue, chunk, mReturnType);
+ }
+ break;
+ case LSCP_EMIT_CIL_ASSEMBLY:
+ {
+ print_cil_load_address(fp, mLValue, entry);
+ mLValue->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ print_cil_mod(fp, mLValue->mReturnType, mRightSide->mReturnType);
+ print_cil_asignment(fp, mLValue, entry);
+ }
+ break;
+ default:
+ mLValue->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ break;
+ }
+ gonext(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+}
+
+S32 LLScriptModAssignment::getSize()
+{
+ return 0;
+}
+
+void print_cil_eq(FILE* fp, LSCRIPTType left_type, LSCRIPTType right_type)
+{
+ switch(left_type)
+ {
+ case LST_INTEGER:
+ case LST_FLOATINGPOINT:
+
+ // Numeric equality.
+ fprintf(fp, "ceq\n");
+ break;
+
+ case LST_STRING:
+ case LST_KEY:
+
+ // String equality.
+ fprintf(fp, "call bool valuetype [mscorlib]System.String::op_Equality(string, string)\n");
+ break;
+
+ case LST_VECTOR:
+
+ // Vector equality.
+ fprintf(fp, "call bool [LScriptLibrary]LLVector::'equals_vec'(valuetype [LScriptLibrary]LLVector, valuetype [LScriptLibrary]LLVector)\n");
+ break;
+
+ case LST_QUATERNION:
+
+ // Rotation equality.
+ fprintf(fp, "call bool [LScriptLibrary]LLQuaternion::'equals_quat'(valuetype [LScriptLibrary]LLQuaternion, valuetype [LScriptLibrary]LLQuaternion)\n");
+ break;
+
+ case LST_LIST:
+ fprintf(fp, "call bool [LScriptLibrary]LScriptInternal::EqualsList(class [mscorlib]System.Collections.ArrayList, class [mscorlib]System.Collections.ArrayList)\n");
+ break;
+
+ default:
+
+ // Error.
+ break;
+ }
+}
+
+void LLScriptEquality::recurse(FILE *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)
+{
+ if (gErrorToText.getErrors())
+ {
+ return;
+ }
+ switch(pass)
+ {
+ case LSCP_PRETTY_PRINT:
+ mLeftSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, " == ");
+ mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ break;
+ case LSCP_EMIT_ASSEMBLY:
+ mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mLeftSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, "EQ %s, %s\n", LSCRIPTTypeNames[mRightType], LSCRIPTTypeNames[mLeftType]);
+ break;
+ case LSCP_TYPE:
+ {
+ mLeftSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mLeftType = type;
+ mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mRightType = type;
+ if (!legal_binary_expression(mReturnType, mLeftType, mRightType, mType))
+ {
+ gErrorToText.writeError(fp, this, LSERROR_TYPE_MISMATCH);
+ }
+ type = mReturnType;
+ }
+ break;
+ case LSCP_TO_STACK:
+ {
+ mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mLeftSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ U8 typebyte = LSCRIPTTypeByte[mRightType] | LSCRIPTTypeHi4Bits[mLeftType];
+ chunk->addByte(LSCRIPTOpCodes[LOPC_EQ]);
+ chunk->addByte(typebyte);
+ }
+ break;
+ case LSCP_EMIT_CIL_ASSEMBLY:
+ mLeftSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ print_cil_numeric_cast(fp, mLeftSide->mReturnType, mRightSide->mReturnType);
+ mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ print_cil_numeric_cast(fp, mRightSide->mReturnType, mLeftSide->mReturnType);
+ print_cil_eq(fp, mLeftSide->mReturnType, mRightSide->mReturnType);
+ break;
+ default:
+ mLeftSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ break;
+ }
+ gonext(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+}
+
+S32 LLScriptEquality::getSize()
+{
+ return 0;
+}
+
+void LLScriptNotEquals::recurse(FILE *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)
+{
+ if (gErrorToText.getErrors())
+ {
+ return;
+ }
+ switch(pass)
+ {
+ case LSCP_PRETTY_PRINT:
+ mLeftSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, " != ");
+ mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ break;
+ case LSCP_EMIT_ASSEMBLY:
+ mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mLeftSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, "NEQ %s, %s\n", LSCRIPTTypeNames[mRightType], LSCRIPTTypeNames[mLeftType]);
+ break;
+ case LSCP_TYPE:
+ {
+ mLeftSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mLeftType = type;
+ mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mRightType = type;
+ if (!legal_binary_expression(mReturnType, mLeftType, mRightType, mType))
+ {
+ gErrorToText.writeError(fp, this, LSERROR_TYPE_MISMATCH);
+ }
+ type = mReturnType;
+ }
+ break;
+ case LSCP_TO_STACK:
+ {
+ mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mLeftSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ U8 typebyte = LSCRIPTTypeByte[mRightType] | LSCRIPTTypeHi4Bits[mLeftType];
+ chunk->addByte(LSCRIPTOpCodes[LOPC_NEQ]);
+ chunk->addByte(typebyte);
+ }
+ break;
+ case LSCP_EMIT_CIL_ASSEMBLY:
+ mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mLeftSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, "ceq\n");
+ fprintf(fp, "ldc.i4.0\n");
+ fprintf(fp, "ceq\n"); // Compare result of first compare equal with 0 to get compare not equal.
+ break;
+ default:
+ mLeftSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ break;
+ }
+ gonext(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+}
+
+S32 LLScriptNotEquals::getSize()
+{
+ return 0;
+}
+
+void LLScriptLessEquals::recurse(FILE *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)
+{
+ if (gErrorToText.getErrors())
+ {
+ return;
+ }
+ switch(pass)
+ {
+ case LSCP_PRETTY_PRINT:
+ mLeftSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, " <= ");
+ mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ break;
+ case LSCP_EMIT_ASSEMBLY:
+ mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mLeftSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, "LEQ %s, %s\n", LSCRIPTTypeNames[mRightType], LSCRIPTTypeNames[mLeftType]);
+ break;
+ case LSCP_TYPE:
+ {
+ mLeftSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mLeftType = type;
+ mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mRightType = type;
+ if (!legal_binary_expression(mReturnType, mLeftType, mRightType, mType))
+ {
+ gErrorToText.writeError(fp, this, LSERROR_TYPE_MISMATCH);
+ }
+ type = mReturnType;
+ }
+ break;
+ case LSCP_TO_STACK:
+ {
+ mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mLeftSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ U8 typebyte = LSCRIPTTypeByte[mRightType] | LSCRIPTTypeHi4Bits[mLeftType];
+ chunk->addByte(LSCRIPTOpCodes[LOPC_LEQ]);
+ chunk->addByte(typebyte);
+ }
+ break;
+ case LSCP_EMIT_CIL_ASSEMBLY:
+ mLeftSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, "cgt\n"); // Test greater than.
+ fprintf(fp, "ldc.i4.0\n"); // Use (b == 0) implementation of boolean not.
+ fprintf(fp, "ceq\n"); // Apply boolean not to greater than. If not greater than, then less or equal.
+ break;
+ default:
+ mLeftSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ break;
+ }
+ gonext(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+}
+
+S32 LLScriptLessEquals::getSize()
+{
+ return 0;
+}
+
+void LLScriptGreaterEquals::recurse(FILE *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)
+{
+ if (gErrorToText.getErrors())
+ {
+ return;
+ }
+ switch(pass)
+ {
+ case LSCP_PRETTY_PRINT:
+ mLeftSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, " >= ");
+ mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ break;
+ case LSCP_EMIT_ASSEMBLY:
+ mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mLeftSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, "GEQ %s, %s\n", LSCRIPTTypeNames[mRightType], LSCRIPTTypeNames[mLeftType]);
+ break;
+ case LSCP_TYPE:
+ {
+ mLeftSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mLeftType = type;
+ mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mRightType = type;
+ if (!legal_binary_expression(mReturnType, mLeftType, mRightType, mType))
+ {
+ gErrorToText.writeError(fp, this, LSERROR_TYPE_MISMATCH);
+ }
+ type = mReturnType;
+ }
+ break;
+ case LSCP_TO_STACK:
+ {
+ mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mLeftSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ U8 typebyte = LSCRIPTTypeByte[mRightType] | LSCRIPTTypeHi4Bits[mLeftType];
+ chunk->addByte(LSCRIPTOpCodes[LOPC_GEQ]);
+ chunk->addByte(typebyte);
+ }
+ break;
+ case LSCP_EMIT_CIL_ASSEMBLY:
+ mLeftSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, "clt\n"); // Test less than.
+ fprintf(fp, "ldc.i4.0\n"); // Use (b == 0) implementation of boolean not.
+ fprintf(fp, "ceq\n"); // Apply boolean not to less than. If not less than, then greater or equal.
+ break;
+ default:
+ mLeftSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ break;
+ }
+ gonext(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+}
+
+S32 LLScriptGreaterEquals::getSize()
+{
+ return 0;
+}
+
+void LLScriptLessThan::recurse(FILE *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)
+{
+ if (gErrorToText.getErrors())
+ {
+ return;
+ }
+ switch(pass)
+ {
+ case LSCP_PRETTY_PRINT:
+ mLeftSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, " < ");
+ mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ break;
+ case LSCP_EMIT_ASSEMBLY:
+ mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mLeftSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, "LESS %s, %s\n", LSCRIPTTypeNames[mRightType], LSCRIPTTypeNames[mLeftType]);
+ break;
+ case LSCP_TYPE:
+ {
+ mLeftSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mLeftType = type;
+ mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mRightType = type;
+ if (!legal_binary_expression(mReturnType, mLeftType, mRightType, mType))
+ {
+ gErrorToText.writeError(fp, this, LSERROR_TYPE_MISMATCH);
+ }
+ type = mReturnType;
+ }
+ break;
+ case LSCP_TO_STACK:
+ {
+ mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mLeftSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ U8 typebyte = LSCRIPTTypeByte[mRightType] | LSCRIPTTypeHi4Bits[mLeftType];
+ chunk->addByte(LSCRIPTOpCodes[LOPC_LESS]);
+ chunk->addByte(typebyte);
+ }
+ break;
+ case LSCP_EMIT_CIL_ASSEMBLY:
+ mLeftSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, "clt\n");
+ break;
+ default:
+ mLeftSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ break;
+ }
+ gonext(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+}
+
+S32 LLScriptLessThan::getSize()
+{
+ return 0;
+}
+
+void LLScriptGreaterThan::recurse(FILE *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)
+{
+ if (gErrorToText.getErrors())
+ {
+ return;
+ }
+ switch(pass)
+ {
+ case LSCP_PRETTY_PRINT:
+ mLeftSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, " > ");
+ mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ break;
+ case LSCP_EMIT_ASSEMBLY:
+ mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mLeftSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, "GREATER %s, %s\n", LSCRIPTTypeNames[mRightType], LSCRIPTTypeNames[mLeftType]);
+ break;
+ case LSCP_TYPE:
+ {
+ mLeftSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mLeftType = type;
+ mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mRightType = type;
+ if (!legal_binary_expression(mReturnType, mLeftType, mRightType, mType))
+ {
+ gErrorToText.writeError(fp, this, LSERROR_TYPE_MISMATCH);
+ }
+ type = mReturnType;
+ }
+ break;
+ case LSCP_TO_STACK:
+ {
+ mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mLeftSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ U8 typebyte = LSCRIPTTypeByte[mRightType] | LSCRIPTTypeHi4Bits[mLeftType];
+ chunk->addByte(LSCRIPTOpCodes[LOPC_GREATER]);
+ chunk->addByte(typebyte);
+ }
+ break;
+ case LSCP_EMIT_CIL_ASSEMBLY:
+ mLeftSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, "cgt\n");
+ break;
+ default:
+ mLeftSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ break;
+ }
+ gonext(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+}
+
+S32 LLScriptGreaterThan::getSize()
+{
+ return 0;
+}
+
+void LLScriptPlus::recurse(FILE *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)
+{
+ if (gErrorToText.getErrors())
+ {
+ return;
+ }
+ switch(pass)
+ {
+ case LSCP_PRETTY_PRINT:
+ mLeftSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, " + ");
+ mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ break;
+ case LSCP_EMIT_ASSEMBLY:
+ mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mLeftSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, "ADD %s, %s\n", LSCRIPTTypeNames[mRightType], LSCRIPTTypeNames[mLeftType]);
+ break;
+ case LSCP_TYPE:
+ {
+ mLeftSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mLeftType = type;
+ mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mRightType = type;
+ if (!legal_binary_expression(mReturnType, mLeftType, mRightType, mType))
+ {
+ gErrorToText.writeError(fp, this, LSERROR_TYPE_MISMATCH);
+ }
+ type = mReturnType;
+ }
+ break;
+ case LSCP_TO_STACK:
+ {
+ mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mLeftSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ U8 typebyte = LSCRIPTTypeByte[mRightType] | LSCRIPTTypeHi4Bits[mLeftType];
+ chunk->addByte(LSCRIPTOpCodes[LOPC_ADD]);
+ chunk->addByte(typebyte);
+ }
+ break;
+ case LSCP_EMIT_CIL_ASSEMBLY:
+ mLeftSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ print_cil_numeric_cast(fp, mLeftSide->mReturnType, mRightSide->mReturnType);
+ mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ print_cil_numeric_cast(fp, mRightSide->mReturnType, mLeftSide->mReturnType);
+ print_cil_add(fp, mLeftSide->mReturnType, mRightSide->mReturnType);
+ break;
+ default:
+ mLeftSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ break;
+ }
+ gonext(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+}
+
+S32 LLScriptPlus::getSize()
+{
+ return 0;
+}
+
+void LLScriptMinus::recurse(FILE *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)
+{
+ if (gErrorToText.getErrors())
+ {
+ return;
+ }
+ switch(pass)
+ {
+ case LSCP_PRETTY_PRINT:
+ mLeftSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, " - ");
+ mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ break;
+ case LSCP_EMIT_ASSEMBLY:
+ mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mLeftSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, "SUB %s, %s\n", LSCRIPTTypeNames[mRightType], LSCRIPTTypeNames[mLeftType]);
+ break;
+ case LSCP_TYPE:
+ {
+ mLeftSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mLeftType = type;
+ mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mRightType = type;
+ if (!legal_binary_expression(mReturnType, mLeftType, mRightType, mType))
+ {
+ gErrorToText.writeError(fp, this, LSERROR_TYPE_MISMATCH);
+ }
+ type = mReturnType;
+ }
+ break;
+ case LSCP_TO_STACK:
+ {
+ mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mLeftSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ U8 typebyte = LSCRIPTTypeByte[mRightType] | LSCRIPTTypeHi4Bits[mLeftType];
+ chunk->addByte(LSCRIPTOpCodes[LOPC_SUB]);
+ chunk->addByte(typebyte);
+ }
+ break;
+ case LSCP_EMIT_CIL_ASSEMBLY:
+ mLeftSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ print_cil_numeric_cast(fp, mLeftSide->mReturnType, mRightSide->mReturnType);
+ mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ print_cil_numeric_cast(fp, mRightSide->mReturnType, mLeftSide->mReturnType);
+ print_cil_sub(fp, mLeftSide->mReturnType, mRightSide->mReturnType);
+ break;
+ default:
+ mLeftSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ break;
+ }
+ gonext(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+}
+
+S32 LLScriptMinus::getSize()
+{
+ return 0;
+}
+
+void LLScriptTimes::recurse(FILE *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)
+{
+ if (gErrorToText.getErrors())
+ {
+ return;
+ }
+ switch(pass)
+ {
+ case LSCP_PRETTY_PRINT:
+ mLeftSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, " * ");
+ mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ break;
+ case LSCP_EMIT_ASSEMBLY:
+ mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mLeftSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, "MUL %s, %s\n", LSCRIPTTypeNames[mRightType], LSCRIPTTypeNames[mLeftType]);
+ break;
+ case LSCP_TYPE:
+ {
+ mLeftSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mLeftType = type;
+ mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mRightType = type;
+ if (!legal_binary_expression(mReturnType, mLeftType, mRightType, mType))
+ {
+ gErrorToText.writeError(fp, this, LSERROR_TYPE_MISMATCH);
+ }
+ type = mReturnType;
+ }
+ break;
+ case LSCP_TO_STACK:
+ {
+ mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mLeftSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ U8 typebyte = LSCRIPTTypeByte[mRightType] | LSCRIPTTypeHi4Bits[mLeftType];
+ chunk->addByte(LSCRIPTOpCodes[LOPC_MUL]);
+ chunk->addByte(typebyte);
+ }
+ break;
+ case LSCP_EMIT_CIL_ASSEMBLY:
+ mLeftSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ print_cil_numeric_cast(fp, mLeftSide->mReturnType, mRightSide->mReturnType);
+ mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ print_cil_numeric_cast(fp, mRightSide->mReturnType, mLeftSide->mReturnType);
+ print_cil_mul(fp, mLeftSide->mReturnType, mRightSide->mReturnType);
+ break;
+ default:
+ mLeftSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ break;
+ }
+ gonext(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+}
+
+S32 LLScriptTimes::getSize()
+{
+ return 0;
+}
+
+void LLScriptDivide::recurse(FILE *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)
+{
+ if (gErrorToText.getErrors())
+ {
+ return;
+ }
+ switch(pass)
+ {
+ case LSCP_PRETTY_PRINT:
+ mLeftSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, " / ");
+ mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ break;
+ case LSCP_EMIT_ASSEMBLY:
+ mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mLeftSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, "DIV %s, %s\n", LSCRIPTTypeNames[mRightType], LSCRIPTTypeNames[mLeftType]);
+ break;
+ case LSCP_TYPE:
+ {
+ mLeftSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mLeftType = type;
+ mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mRightType = type;
+ if (!legal_binary_expression(mReturnType, mLeftType, mRightType, mType))
+ {
+ gErrorToText.writeError(fp, this, LSERROR_TYPE_MISMATCH);
+ }
+ type = mReturnType;
+ }
+ break;
+ case LSCP_TO_STACK:
+ {
+ mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mLeftSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ U8 typebyte = LSCRIPTTypeByte[mRightType] | LSCRIPTTypeHi4Bits[mLeftType];
+ chunk->addByte(LSCRIPTOpCodes[LOPC_DIV]);
+ chunk->addByte(typebyte);
+ }
+ break;
+ case LSCP_EMIT_CIL_ASSEMBLY:
+ mLeftSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ print_cil_numeric_cast(fp, mLeftSide->mReturnType, mRightSide->mReturnType);
+ mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ print_cil_numeric_cast(fp, mRightSide->mReturnType, mLeftSide->mReturnType);
+ print_cil_div(fp, mLeftSide->mReturnType, mRightSide->mReturnType);
+ break;
+ default:
+ mLeftSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ break;
+ }
+ gonext(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+}
+
+S32 LLScriptDivide::getSize()
+{
+ return 0;
+}
+
+void LLScriptMod::recurse(FILE *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)
+{
+ if (gErrorToText.getErrors())
+ {
+ return;
+ }
+ switch(pass)
+ {
+ case LSCP_PRETTY_PRINT:
+ mLeftSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, " %% ");
+ mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ break;
+ case LSCP_EMIT_ASSEMBLY:
+ mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mLeftSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, "MOD %s, %s\n", LSCRIPTTypeNames[mRightType], LSCRIPTTypeNames[mLeftType]);
+ break;
+ case LSCP_TYPE:
+ {
+ mLeftSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mLeftType = type;
+ mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mRightType = type;
+ if (!legal_binary_expression(mReturnType, mLeftType, mRightType, mType))
+ {
+ gErrorToText.writeError(fp, this, LSERROR_TYPE_MISMATCH);
+ }
+ type = mReturnType;
+ }
+ break;
+ case LSCP_TO_STACK:
+ {
+ mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mLeftSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ U8 typebyte = LSCRIPTTypeByte[mRightType] | LSCRIPTTypeHi4Bits[mLeftType];
+ chunk->addByte(LSCRIPTOpCodes[LOPC_MOD]);
+ chunk->addByte(typebyte);
+ }
+ break;
+ case LSCP_EMIT_CIL_ASSEMBLY:
+ mLeftSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ print_cil_mod(fp, mLeftSide->mReturnType, mRightSide->mReturnType);
+ break;
+ default:
+ mLeftSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ break;
+ }
+ gonext(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+}
+
+S32 LLScriptMod::getSize()
+{
+ return 0;
+}
+
+void LLScriptBitAnd::recurse(FILE *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)
+{
+ if (gErrorToText.getErrors())
+ {
+ return;
+ }
+ switch(pass)
+ {
+ case LSCP_PRETTY_PRINT:
+ mLeftSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, " & ");
+ mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ break;
+ case LSCP_EMIT_ASSEMBLY:
+ mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mLeftSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, "BITAND\n");
+ break;
+ case LSCP_TYPE:
+ {
+ mLeftSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mLeftType = type;
+ mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mRightType = type;
+ if (!legal_binary_expression(mReturnType, mLeftType, mRightType, mType))
+ {
+ gErrorToText.writeError(fp, this, LSERROR_TYPE_MISMATCH);
+ }
+ type = mReturnType;
+ }
+ break;
+ case LSCP_TO_STACK:
+ {
+ mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mLeftSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ chunk->addByte(LSCRIPTOpCodes[LOPC_BITAND]);
+ }
+ break;
+ case LSCP_EMIT_CIL_ASSEMBLY:
+ mLeftSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, "and\n");
+ break;
+ default:
+ mLeftSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ break;
+ }
+ gonext(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+}
+
+S32 LLScriptBitAnd::getSize()
+{
+ return 0;
+}
+
+void LLScriptBitOr::recurse(FILE *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)
+{
+ if (gErrorToText.getErrors())
+ {
+ return;
+ }
+ switch(pass)
+ {
+ case LSCP_PRETTY_PRINT:
+ mLeftSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, " | ");
+ mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ break;
+ case LSCP_EMIT_ASSEMBLY:
+ mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mLeftSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, "BITOR\n");
+ break;
+ case LSCP_TYPE:
+ {
+ mLeftSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mLeftType = type;
+ mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mRightType = type;
+ if (!legal_binary_expression(mReturnType, mLeftType, mRightType, mType))
+ {
+ gErrorToText.writeError(fp, this, LSERROR_TYPE_MISMATCH);
+ }
+ type = mReturnType;
+ }
+ break;
+ case LSCP_TO_STACK:
+ {
+ mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mLeftSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ chunk->addByte(LSCRIPTOpCodes[LOPC_BITOR]);
+ }
+ break;
+ case LSCP_EMIT_CIL_ASSEMBLY:
+ mLeftSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, "or\n");
+ break;
+ default:
+ mLeftSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ break;
+ }
+ gonext(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+}
+
+S32 LLScriptBitOr::getSize()
+{
+ return 0;
+}
+
+void LLScriptBitXor::recurse(FILE *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)
+{
+ if (gErrorToText.getErrors())
+ {
+ return;
+ }
+ switch(pass)
+ {
+ case LSCP_PRETTY_PRINT:
+ mLeftSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, " ^ ");
+ mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ break;
+ case LSCP_EMIT_ASSEMBLY:
+ mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mLeftSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, "BITXOR\n");
+ break;
+ case LSCP_TYPE:
+ {
+ mLeftSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mLeftType = type;
+ mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mRightType = type;
+ if (!legal_binary_expression(mReturnType, mLeftType, mRightType, mType))
+ {
+ gErrorToText.writeError(fp, this, LSERROR_TYPE_MISMATCH);
+ }
+ type = mReturnType;
+ }
+ break;
+ case LSCP_TO_STACK:
+ {
+ mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mLeftSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ chunk->addByte(LSCRIPTOpCodes[LOPC_BITXOR]);
+ }
+ break;
+ case LSCP_EMIT_CIL_ASSEMBLY:
+ mLeftSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, "xor\n");
+ break;
+ default:
+ mLeftSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ break;
+ }
+ gonext(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+}
+
+S32 LLScriptBitXor::getSize()
+{
+ return 0;
+}
+
+void LLScriptBooleanAnd::recurse(FILE *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)
+{
+ if (gErrorToText.getErrors())
+ {
+ return;
+ }
+ switch(pass)
+ {
+ case LSCP_PRETTY_PRINT:
+ mLeftSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, " && ");
+ mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ break;
+ case LSCP_EMIT_ASSEMBLY:
+ mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mLeftSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, "BOOLAND\n");
+ break;
+ case LSCP_TYPE:
+ {
+ mLeftSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mLeftType = type;
+ mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mRightType = type;
+ if (!legal_binary_expression(mReturnType, mLeftType, mRightType, mType))
+ {
+ gErrorToText.writeError(fp, this, LSERROR_TYPE_MISMATCH);
+ }
+ type = mReturnType;
+ }
+ break;
+ case LSCP_TO_STACK:
+ {
+ mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mLeftSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ chunk->addByte(LSCRIPTOpCodes[LOPC_BOOLAND]);
+ }
+ break;
+ case LSCP_EMIT_CIL_ASSEMBLY:
+ mLeftSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, "and\n");
+ break;
+ default:
+ mLeftSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ break;
+ }
+ gonext(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+}
+
+S32 LLScriptBooleanAnd::getSize()
+{
+ return 0;
+}
+
+void LLScriptBooleanOr::recurse(FILE *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)
+{
+ if (gErrorToText.getErrors())
+ {
+ return;
+ }
+ switch(pass)
+ {
+ case LSCP_PRETTY_PRINT:
+ mLeftSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, " || ");
+ mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ break;
+ case LSCP_EMIT_ASSEMBLY:
+ mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mLeftSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, "BOOLOR\n");
+ break;
+ case LSCP_TYPE:
+ {
+ mLeftSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mLeftType = type;
+ mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mRightType = type;
+ if (!legal_binary_expression(mReturnType, mLeftType, mRightType, mType))
+ {
+ gErrorToText.writeError(fp, this, LSERROR_TYPE_MISMATCH);
+ }
+ type = mReturnType;
+ }
+ break;
+ case LSCP_TO_STACK:
+ {
+ mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mLeftSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ chunk->addByte(LSCRIPTOpCodes[LOPC_BOOLOR]);
+ }
+ break;
+ case LSCP_EMIT_CIL_ASSEMBLY:
+ mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mLeftSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, "or\n");
+ break;
+ default:
+ mLeftSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ break;
+ }
+ gonext(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+}
+
+S32 LLScriptBooleanOr::getSize()
+{
+ return 0;
+}
+
+void LLScriptShiftLeft::recurse(FILE *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)
+{
+ if (gErrorToText.getErrors())
+ {
+ return;
+ }
+ switch(pass)
+ {
+ case LSCP_PRETTY_PRINT:
+ mLeftSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, " << ");
+ mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ break;
+ case LSCP_EMIT_ASSEMBLY:
+ mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mLeftSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, "SHL\n");
+ break;
+ case LSCP_TYPE:
+ {
+ mLeftSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mLeftType = type;
+ mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mRightType = type;
+ if (!legal_binary_expression(mReturnType, mLeftType, mRightType, mType))
+ {
+ gErrorToText.writeError(fp, this, LSERROR_TYPE_MISMATCH);
+ }
+ type = mReturnType;
+ }
+ break;
+ case LSCP_TO_STACK:
+ {
+ mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mLeftSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ chunk->addByte(LSCRIPTOpCodes[LOPC_SHL]);
+ }
+ break;
+ case LSCP_EMIT_CIL_ASSEMBLY:
+ mLeftSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, "shl\n");
+ break;
+ default:
+ mLeftSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ break;
+ }
+ gonext(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+}
+
+S32 LLScriptShiftLeft::getSize()
+{
+ return 0;
+}
+
+
+void LLScriptShiftRight::recurse(FILE *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)
+{
+ if (gErrorToText.getErrors())
+ {
+ return;
+ }
+ switch(pass)
+ {
+ case LSCP_PRETTY_PRINT:
+ mLeftSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, " >> ");
+ mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ break;
+ case LSCP_EMIT_ASSEMBLY:
+ mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mLeftSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, "SHR\n");
+ break;
+ case LSCP_TYPE:
+ {
+ mLeftSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mLeftType = type;
+ mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mRightType = type;
+ if (!legal_binary_expression(mReturnType, mLeftType, mRightType, mType))
+ {
+ gErrorToText.writeError(fp, this, LSERROR_TYPE_MISMATCH);
+ }
+ type = mReturnType;
+ }
+ break;
+ case LSCP_TO_STACK:
+ {
+ mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mLeftSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ chunk->addByte(LSCRIPTOpCodes[LOPC_SHR]);
+ }
+ break;
+ case LSCP_EMIT_CIL_ASSEMBLY:
+ mLeftSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, "shr\n");
+ break;
+ default:
+ mLeftSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ break;
+ }
+ gonext(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+}
+
+S32 LLScriptShiftRight::getSize()
+{
+ return 0;
+}
+
+void LLScriptParenthesis::recurse(FILE *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)
+{
+ if (gErrorToText.getErrors())
+ {
+ return;
+ }
+ switch(pass)
+ {
+ case LSCP_PRETTY_PRINT:
+ fprintf(fp, "( ");
+ mExpression->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, " )");
+ break;
+ case LSCP_TYPE:
+ mExpression->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mReturnType = mLeftType = type;
+ break;
+ case LSCP_EMIT_ASSEMBLY:
+ mExpression->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mReturnType = mLeftType = type;
+ break;
+ default:
+ mExpression->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ break;
+ }
+ gonext(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+}
+
+S32 LLScriptParenthesis::getSize()
+{
+ return 0;
+}
+
+void LLScriptUnaryMinus::recurse(FILE *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)
+{
+ if (gErrorToText.getErrors())
+ {
+ return;
+ }
+ switch(pass)
+ {
+ case LSCP_PRETTY_PRINT:
+ fprintf(fp, "-");
+ mExpression->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ break;
+ case LSCP_EMIT_ASSEMBLY:
+ mExpression->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, "NEG %s\n", LSCRIPTTypeNames[mLeftType]);
+ break;
+ case LSCP_TYPE:
+ mExpression->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ if (!legal_unary_expression(type, type, mType))
+ {
+ gErrorToText.writeError(fp, this, LSERROR_TYPE_MISMATCH);
+ }
+ else
+ {
+ mReturnType = mLeftType = type;
+ }
+ break;
+ case LSCP_TO_STACK:
+ {
+ mExpression->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ U8 typebyte = LSCRIPTTypeByte[mLeftType];
+ chunk->addByte(LSCRIPTOpCodes[LOPC_NEG]);
+ chunk->addByte(typebyte);
+ }
+ break;
+ default:
+ mExpression->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ break;
+ }
+ gonext(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+}
+
+S32 LLScriptUnaryMinus::getSize()
+{
+ return 0;
+}
+
+void LLScriptBooleanNot::recurse(FILE *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)
+{
+ if (gErrorToText.getErrors())
+ {
+ return;
+ }
+ switch(pass)
+ {
+ case LSCP_PRETTY_PRINT:
+ fprintf(fp, "!");
+ mExpression->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ break;
+ case LSCP_EMIT_ASSEMBLY:
+ mExpression->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, "BOOLNOT\n");
+ break;
+ case LSCP_TYPE:
+ mExpression->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ if (!legal_unary_expression(type, type, mType))
+ {
+ gErrorToText.writeError(fp, this, LSERROR_TYPE_MISMATCH);
+ }
+ else
+ {
+ mReturnType = mLeftType = type;
+ }
+ break;
+ case LSCP_TO_STACK:
+ {
+ mExpression->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ chunk->addByte(LSCRIPTOpCodes[LOPC_BOOLNOT]);
+ }
+ break;
+ case LSCP_EMIT_CIL_ASSEMBLY:
+ mExpression->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, "ldc.i4.0\n");
+ fprintf(fp, "ceq\n"); // If f(e) is (e == 0), f(e) returns 1 if e is 0 and 0 otherwise, therefore f(e) implements boolean not.
+ break;
+ default:
+ mExpression->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ break;
+ }
+ gonext(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+}
+
+S32 LLScriptBooleanNot::getSize()
+{
+ return 0;
+}
+
+void LLScriptBitNot::recurse(FILE *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)
+{
+ if (gErrorToText.getErrors())
+ {
+ return;
+ }
+ switch(pass)
+ {
+ case LSCP_PRETTY_PRINT:
+ fprintf(fp, "~");
+ mExpression->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ break;
+ case LSCP_EMIT_ASSEMBLY:
+ mExpression->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, "BITNOT\n");
+ break;
+ case LSCP_TYPE:
+ mExpression->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ if (!legal_unary_expression(type, type, mType))
+ {
+ gErrorToText.writeError(fp, this, LSERROR_TYPE_MISMATCH);
+ }
+ else
+ {
+ mReturnType = mLeftType = type;
+ }
+ break;
+ case LSCP_TO_STACK:
+ {
+ mExpression->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ chunk->addByte(LSCRIPTOpCodes[LOPC_BITNOT]);
+ }
+ break;
+ case LSCP_EMIT_CIL_ASSEMBLY:
+ mExpression->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, "not\n");
+ break;
+ default:
+ mExpression->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ break;
+ }
+ gonext(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+}
+
+S32 LLScriptBitNot::getSize()
+{
+ return 0;
+}
+
+void LLScriptPreIncrement::recurse(FILE *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)
+{
+ if (gErrorToText.getErrors())
+ {
+ return;
+ }
+ switch(pass)
+ {
+ case LSCP_PRETTY_PRINT:
+ fprintf(fp, "++");
+ mExpression->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ break;
+ case LSCP_EMIT_ASSEMBLY:
+ {
+ if (mReturnType == LST_INTEGER)
+ {
+ fprintf(fp, "PUSHARGI 1\n");
+ mExpression->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, "\n");
+ fprintf(fp, "ADD integer, integer\n");
+ }
+ else if (mReturnType == LST_FLOATINGPOINT)
+ {
+ fprintf(fp, "PUSHARGF 1\n");
+ mExpression->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, "\n");
+ fprintf(fp, "ADD float, float\n");
+ }
+ else
+ {
+ fprintf(fp, "Unexpected Type\n");
+ }
+ print_asignment(fp, mExpression);
+ }
+ break;
+ case LSCP_TYPE:
+ if (mExpression->mType != LET_LVALUE)
+ {
+ gErrorToText.writeError(fp, this, LSERROR_EXPRESSION_ON_LVALUE);
+ }
+ else
+ {
+ mExpression->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ if (!legal_unary_expression(type, type, mType))
+ {
+ gErrorToText.writeError(fp, this, LSERROR_TYPE_MISMATCH);
+ }
+ else
+ {
+ mReturnType = mLeftType = type;
+ }
+ }
+ break;
+ case LSCP_TO_STACK:
+ {
+ if (mReturnType == LST_INTEGER)
+ {
+ chunk->addByte(LSCRIPTOpCodes[LOPC_PUSHARGI]);
+ chunk->addInteger(1);
+ mExpression->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ chunk->addByte(LSCRIPTOpCodes[LOPC_ADD]);
+ chunk->addByte(LSCRIPTTypeByte[LST_INTEGER] | LSCRIPTTypeHi4Bits[LST_INTEGER]);
+ }
+ else if (mReturnType == LST_FLOATINGPOINT)
+ {
+ chunk->addByte(LSCRIPTOpCodes[LOPC_PUSHARGF]);
+ chunk->addFloat(1.f);
+ mExpression->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ chunk->addByte(LSCRIPTOpCodes[LOPC_ADD]);
+ chunk->addByte(LSCRIPTTypeByte[LST_FLOATINGPOINT] | LSCRIPTTypeHi4Bits[LST_FLOATINGPOINT]);
+ }
+ store2stack(this, mExpression, chunk, mReturnType);
+ }
+ break;
+ case LSCP_EMIT_CIL_ASSEMBLY:
+ {
+ print_cil_load_address(fp, mExpression, entry);
+ if (mReturnType == LST_INTEGER)
+ {
+ fprintf(fp, "ldc.i4.1\n");
+ mExpression->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, "add\n");
+ }
+ else if (mReturnType == LST_FLOATINGPOINT)
+ {
+ fprintf(fp, "ldc.r8.1\n");
+ mExpression->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, "add\n");
+ }
+ else
+ {
+ fprintf(fp, "Unexpected Type\n");
+ }
+ print_cil_asignment(fp, mExpression, entry);
+ }
+ break;
+ default:
+ mExpression->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ break;
+ }
+ gonext(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+}
+
+S32 LLScriptPreIncrement::getSize()
+{
+ return 0;
+}
+
+void LLScriptPreDecrement::recurse(FILE *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)
+{
+ if (gErrorToText.getErrors())
+ {
+ return;
+ }
+ switch(pass)
+ {
+ case LSCP_PRETTY_PRINT:
+ fprintf(fp, "--");
+ mExpression->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ break;
+ case LSCP_EMIT_ASSEMBLY:
+ {
+ if (mReturnType == LST_INTEGER)
+ {
+ fprintf(fp, "PUSHARGI 1\n");
+ mExpression->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, "\n");
+ fprintf(fp, "SUB integer, integer\n");
+ }
+ else if (mReturnType == LST_FLOATINGPOINT)
+ {
+ fprintf(fp, "PUSHARGF 1\n");
+ mExpression->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, "\n");
+ fprintf(fp, "SUB float, float\n");
+ }
+ else
+ {
+ fprintf(fp, "Unexpected Type\n");
+ }
+ print_asignment(fp, mExpression);
+ }
+ break;
+ case LSCP_TYPE:
+ if (mExpression->mType != LET_LVALUE)
+ {
+ gErrorToText.writeError(fp, this, LSERROR_EXPRESSION_ON_LVALUE);
+ }
+ else
+ {
+ mExpression->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ if (!legal_unary_expression(type, type, mType))
+ {
+ gErrorToText.writeError(fp, this, LSERROR_TYPE_MISMATCH);
+ }
+ else
+ {
+ mReturnType = mLeftType = type;
+ }
+ }
+ break;
+ case LSCP_TO_STACK:
+ {
+ if (mReturnType == LST_INTEGER)
+ {
+ chunk->addByte(LSCRIPTOpCodes[LOPC_PUSHARGI]);
+ chunk->addInteger(1);
+ mExpression->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ chunk->addByte(LSCRIPTOpCodes[LOPC_SUB]);
+ chunk->addByte(LSCRIPTTypeByte[LST_INTEGER] | LSCRIPTTypeHi4Bits[LST_INTEGER]);
+ }
+ else if (mReturnType == LST_FLOATINGPOINT)
+ {
+ chunk->addByte(LSCRIPTOpCodes[LOPC_PUSHARGF]);
+ chunk->addFloat(1.f);
+ mExpression->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ chunk->addByte(LSCRIPTOpCodes[LOPC_SUB]);
+ chunk->addByte(LSCRIPTTypeByte[LST_FLOATINGPOINT] | LSCRIPTTypeHi4Bits[LST_FLOATINGPOINT]);
+ }
+ store2stack(this, mExpression, chunk, mReturnType);
+ }
+ break;
+ case LSCP_EMIT_CIL_ASSEMBLY:
+ {
+ print_cil_load_address(fp, mExpression, entry);
+ if (mReturnType == LST_INTEGER)
+ {
+ fprintf(fp, "ldc.i4.1\n");
+ mExpression->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, "sub\n");
+ }
+ else if (mReturnType == LST_FLOATINGPOINT)
+ {
+ fprintf(fp, "ldc.r8.1\n");
+ mExpression->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, "sub\n");
+ }
+ else
+ {
+ fprintf(fp, "Unexpected Type\n");
+ }
+ print_cil_asignment(fp, mExpression, entry);
+ }
+ break;
+ default:
+ mExpression->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ break;
+ }
+ gonext(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+}
+
+S32 LLScriptPreDecrement::getSize()
+{
+ return 0;
+}
+
+void LLScriptTypeCast::recurse(FILE *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)
+{
+ if (gErrorToText.getErrors())
+ {
+ return;
+ }
+ switch(pass)
+ {
+ case LSCP_PRETTY_PRINT:
+ fprintf(fp, "( ");
+ mType->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, ") ");
+ mExpression->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ break;
+ case LSCP_EMIT_ASSEMBLY:
+ fprintf(fp, "CAST %s->%s\n", LSCRIPTTypeNames[mRightType], LSCRIPTTypeNames[mType->mType]);
+ break;
+ case LSCP_TYPE:
+ mExpression->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mRightType = type;
+ if (!legal_casts(mType->mType, type))
+ {
+ gErrorToText.writeError(fp, this, LSERROR_TYPE_MISMATCH);
+ }
+ type = mType->mType;
+ mReturnType = mLeftType = type;
+ break;
+ case LSCP_TO_STACK:
+ {
+ mExpression->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ chunk->addByte(LSCRIPTOpCodes[LOPC_CAST]);
+ U8 castbyte = LSCRIPTTypeByte[mType->mType] | LSCRIPTTypeHi4Bits[mRightType];
+ chunk->addByte(castbyte);
+ }
+ break;
+ case LSCP_EMIT_CIL_ASSEMBLY:
+ mExpression->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ print_cil_cast(fp, mRightType, mType->mType);
+ break;
+ default:
+ mType->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mExpression->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ break;
+ }
+ gonext(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+}
+
+S32 LLScriptTypeCast::getSize()
+{
+ return 0;
+}
+
+void LLScriptVectorInitializer::recurse(FILE *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)
+{
+ if (gErrorToText.getErrors())
+ {
+ return;
+ }
+ switch(pass)
+ {
+ case LSCP_PRETTY_PRINT:
+ fprintf(fp, "< ");
+ mExpression1->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, ", ");
+ mExpression2->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, ", ");
+ mExpression3->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, " >");
+ break;
+ case LSCP_EMIT_ASSEMBLY:
+ mExpression1->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ if (mExpression1->mReturnType != LST_FLOATINGPOINT)
+ {
+ fprintf(fp, "CAST %s->%s\n", LSCRIPTTypeNames[mExpression1->mReturnType], LSCRIPTTypeNames[LST_FLOATINGPOINT]);
+ }
+ mExpression2->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ if (mExpression2->mReturnType != LST_FLOATINGPOINT)
+ {
+ fprintf(fp, "CAST %s->%s\n", LSCRIPTTypeNames[mExpression2->mReturnType], LSCRIPTTypeNames[LST_FLOATINGPOINT]);
+ }
+ mExpression3->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ if (mExpression3->mReturnType != LST_FLOATINGPOINT)
+ {
+ fprintf(fp, "CAST %s->%s\n", LSCRIPTTypeNames[mExpression3->mReturnType], LSCRIPTTypeNames[LST_FLOATINGPOINT]);
+ }
+ break;
+ case LSCP_TYPE:
+ // vector's take floats
+ mExpression1->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ if (!legal_assignment(LST_FLOATINGPOINT, type))
+ {
+ gErrorToText.writeError(fp, this, LSERROR_TYPE_MISMATCH);
+ }
+ mExpression2->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ if (!legal_assignment(LST_FLOATINGPOINT, type))
+ {
+ gErrorToText.writeError(fp, this, LSERROR_TYPE_MISMATCH);
+ }
+ mExpression3->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ if (!legal_assignment(LST_FLOATINGPOINT, type))
+ {
+ gErrorToText.writeError(fp, this, LSERROR_TYPE_MISMATCH);
+ }
+ mReturnType = type = LST_VECTOR;
+ if (mNextp)
+ {
+ mNextp->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ }
+ break;
+ case LSCP_TO_STACK:
+ pass = LSCP_TO_STACK;
+ mExpression1->recurse(fp, tabs, tabsize, LSCP_TO_STACK, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ if (mExpression1->mReturnType != LST_FLOATINGPOINT)
+ {
+ chunk->addByte(LSCRIPTOpCodes[LOPC_CAST]);
+ U8 castbyte = LSCRIPTTypeByte[LST_FLOATINGPOINT] | LSCRIPTTypeHi4Bits[mExpression1->mReturnType];
+ chunk->addByte(castbyte);
+ }
+ mExpression2->recurse(fp, tabs, tabsize, LSCP_TO_STACK, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ if (mExpression2->mReturnType != LST_FLOATINGPOINT)
+ {
+ chunk->addByte(LSCRIPTOpCodes[LOPC_CAST]);
+ U8 castbyte = LSCRIPTTypeByte[LST_FLOATINGPOINT] | LSCRIPTTypeHi4Bits[mExpression2->mReturnType];
+ chunk->addByte(castbyte);
+ }
+ mExpression3->recurse(fp, tabs, tabsize, LSCP_TO_STACK, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ if (mExpression3->mReturnType != LST_FLOATINGPOINT)
+ {
+ chunk->addByte(LSCRIPTOpCodes[LOPC_CAST]);
+ U8 castbyte = LSCRIPTTypeByte[LST_FLOATINGPOINT] | LSCRIPTTypeHi4Bits[mExpression3->mReturnType];
+ chunk->addByte(castbyte);
+ }
+ break;
+ case LSCP_EMIT_CIL_ASSEMBLY:
+
+ // Load arguments.
+ mExpression1->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ if (mExpression1->mReturnType != LST_FLOATINGPOINT)
+ {
+ print_cil_cast(fp, mExpression1->mReturnType, LST_FLOATINGPOINT);
+ }
+ mExpression2->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ if (mExpression2->mReturnType != LST_FLOATINGPOINT)
+ {
+ print_cil_cast(fp, mExpression2->mReturnType, LST_FLOATINGPOINT);
+ }
+ mExpression3->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ if (mExpression3->mReturnType != LST_FLOATINGPOINT)
+ {
+ print_cil_cast(fp, mExpression3->mReturnType, LST_FLOATINGPOINT);
+ }
+ // Call named ctor, which leaves new Vector on stack, so it can be saved in to local or argument just like a primitive type.
+ fprintf(fp, "call valuetype [LScriptLibrary]LLVector valuetype [LScriptLibrary]LLVector::'create'(float32, float32, float32)\n");
+ break;
+ default:
+ mExpression1->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mExpression2->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mExpression3->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ break;
+ }
+ gonext(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+}
+
+S32 LLScriptVectorInitializer::getSize()
+{
+ return 0;
+}
+
+void LLScriptQuaternionInitializer::recurse(FILE *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)
+{
+ if (gErrorToText.getErrors())
+ {
+ return;
+ }
+ switch(pass)
+ {
+ case LSCP_PRETTY_PRINT:
+ fprintf(fp, "< ");
+ mExpression1->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, ", ");
+ mExpression2->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, ", ");
+ mExpression3->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, ", ");
+ mExpression4->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, " >");
+ break;
+ case LSCP_EMIT_ASSEMBLY:
+ mExpression1->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ if (mExpression1->mReturnType != LST_FLOATINGPOINT)
+ {
+ fprintf(fp, "CAST %s->%s\n", LSCRIPTTypeNames[mExpression1->mReturnType], LSCRIPTTypeNames[LST_FLOATINGPOINT]);
+ }
+ mExpression2->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ if (mExpression2->mReturnType != LST_FLOATINGPOINT)
+ {
+ fprintf(fp, "CAST %s->%s\n", LSCRIPTTypeNames[mExpression2->mReturnType], LSCRIPTTypeNames[LST_FLOATINGPOINT]);
+ }
+ mExpression3->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ if (mExpression3->mReturnType != LST_FLOATINGPOINT)
+ {
+ fprintf(fp, "CAST %s->%s\n", LSCRIPTTypeNames[mExpression3->mReturnType], LSCRIPTTypeNames[LST_FLOATINGPOINT]);
+ }
+ mExpression4->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ if (mExpression4->mReturnType != LST_FLOATINGPOINT)
+ {
+ fprintf(fp, "CAST %s->%s\n", LSCRIPTTypeNames[mExpression4->mReturnType], LSCRIPTTypeNames[LST_FLOATINGPOINT]);
+ }
+ break;
+ case LSCP_TYPE:
+ // vector's take floats
+ mExpression1->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ if (!legal_assignment(LST_FLOATINGPOINT, type))
+ {
+ gErrorToText.writeError(fp, this, LSERROR_TYPE_MISMATCH);
+ }
+ mExpression2->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ if (!legal_assignment(LST_FLOATINGPOINT, type))
+ {
+ gErrorToText.writeError(fp, this, LSERROR_TYPE_MISMATCH);
+ }
+ mExpression3->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ if (!legal_assignment(LST_FLOATINGPOINT, type))
+ {
+ gErrorToText.writeError(fp, this, LSERROR_TYPE_MISMATCH);
+ }
+ mExpression4->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ if (!legal_assignment(LST_FLOATINGPOINT, type))
+ {
+ gErrorToText.writeError(fp, this, LSERROR_TYPE_MISMATCH);
+ }
+ mReturnType = type = LST_QUATERNION;
+ if (mNextp)
+ {
+ mNextp->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ }
+ break;
+ case LSCP_TO_STACK:
+ pass = LSCP_TO_STACK;
+ mExpression1->recurse(fp, tabs, tabsize, LSCP_TO_STACK, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ if (mExpression1->mReturnType != LST_FLOATINGPOINT)
+ {
+ chunk->addByte(LSCRIPTOpCodes[LOPC_CAST]);
+ U8 castbyte = LSCRIPTTypeByte[LST_FLOATINGPOINT] | LSCRIPTTypeHi4Bits[mExpression1->mReturnType];
+ chunk->addByte(castbyte);
+ }
+ mExpression2->recurse(fp, tabs, tabsize, LSCP_TO_STACK, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ if (mExpression2->mReturnType != LST_FLOATINGPOINT)
+ {
+ chunk->addByte(LSCRIPTOpCodes[LOPC_CAST]);
+ U8 castbyte = LSCRIPTTypeByte[LST_FLOATINGPOINT] | LSCRIPTTypeHi4Bits[mExpression2->mReturnType];
+ chunk->addByte(castbyte);
+ }
+ mExpression3->recurse(fp, tabs, tabsize, LSCP_TO_STACK, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ if (mExpression3->mReturnType != LST_FLOATINGPOINT)
+ {
+ chunk->addByte(LSCRIPTOpCodes[LOPC_CAST]);
+ U8 castbyte = LSCRIPTTypeByte[LST_FLOATINGPOINT] | LSCRIPTTypeHi4Bits[mExpression3->mReturnType];
+ chunk->addByte(castbyte);
+ }
+ mExpression4->recurse(fp, tabs, tabsize, LSCP_TO_STACK, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ if (mExpression4->mReturnType != LST_FLOATINGPOINT)
+ {
+ chunk->addByte(LSCRIPTOpCodes[LOPC_CAST]);
+ U8 castbyte = LSCRIPTTypeByte[LST_FLOATINGPOINT] | LSCRIPTTypeHi4Bits[mExpression4->mReturnType];
+ chunk->addByte(castbyte);
+ }
+ break;
+ case LSCP_EMIT_CIL_ASSEMBLY:
+
+ // Load arguments.
+ mExpression1->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ if (mExpression1->mReturnType != LST_FLOATINGPOINT)
+ {
+ print_cil_cast(fp, mExpression1->mReturnType, LST_FLOATINGPOINT);
+ }
+ mExpression2->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ if (mExpression2->mReturnType != LST_FLOATINGPOINT)
+ {
+ print_cil_cast(fp, mExpression2->mReturnType, LST_FLOATINGPOINT);
+ }
+ mExpression3->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ if (mExpression3->mReturnType != LST_FLOATINGPOINT)
+ {
+ print_cil_cast(fp, mExpression3->mReturnType, LST_FLOATINGPOINT);
+ }
+ mExpression4->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ if (mExpression4->mReturnType != LST_FLOATINGPOINT)
+ {
+ print_cil_cast(fp, mExpression4->mReturnType, LST_FLOATINGPOINT);
+ }
+
+ // Call named ctor, which leaves new Vector on stack, so it can be saved in to local or argument just like a primitive type.
+ fprintf(fp, "call valuetype [LScriptLibrary]LLQuaternion valuetype [LScriptLibrary]LLQuaternion::'create'(float32, float32, float32, float32)\n");
+ break;
+ default:
+ mExpression1->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mExpression2->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mExpression3->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mExpression4->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ break;
+ }
+ gonext(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+}
+
+S32 LLScriptQuaternionInitializer::getSize()
+{
+ return 0;
+}
+
+void LLScriptListInitializer::recurse(FILE *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)
+{
+ if (gErrorToText.getErrors())
+ {
+ return;
+ }
+ switch(pass)
+ {
+ case LSCP_PRETTY_PRINT:
+ fprintf(fp, "[ ");
+ mExpressionList->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, " ]");
+ break;
+ case LSCP_EMIT_ASSEMBLY:
+ count = 0;
+ if (mExpressionList)
+ {
+ mExpressionList->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, "STACKTOL %llu\n", count);
+ }
+ break;
+ case LSCP_TYPE:
+ if (mExpressionList)
+ {
+ mExpressionList->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mReturnType = type = LST_LIST;
+ }
+ mReturnType = type = LST_LIST;
+ break;
+ case LSCP_TO_STACK:
+ if (mExpressionList)
+ {
+ pass = LSCP_TO_STACK;
+ count = 0;
+ mExpressionList->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ chunk->addByte(LSCRIPTOpCodes[LOPC_STACKTOL]);
+ chunk->addInteger((S32)count);
+ count = 0;
+ }
+ else
+ {
+ chunk->addByte(LSCRIPTOpCodes[LOPC_STACKTOL]);
+ chunk->addInteger(0);
+ }
+ break;
+ case LSCP_EMIT_CIL_ASSEMBLY:
+
+ // Push boxed elements on stack.
+ count = 0;
+ if (mExpressionList)
+ {
+ mExpressionList->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ }
+
+ // Create list on stack, consuming first boxed element.
+ fprintf(fp, "call class [mscorlib]System.Collections.ArrayList class [LScriptLibrary]LScriptInternal::CreateList()\n");
+
+ // Call AddReturnList to add remaining boxed expressions.
+ for(U64 i = 0; i < count; i++)
+ {
+ fprintf(fp, "call class [mscorlib]System.Collections.ArrayList class [LScriptLibrary]LScriptInternal::AddReturnList(object, class [mscorlib]System.Collections.ArrayList)\n");
+ }
+ count = 0;
+
+ break;
+ default:
+ if (mExpressionList)
+ {
+ mExpressionList->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ }
+ break;
+ }
+ gonext(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+}
+
+S32 LLScriptListInitializer::getSize()
+{
+ return 0;
+}
+
+void LLScriptPostIncrement::recurse(FILE *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)
+{
+ if (gErrorToText.getErrors())
+ {
+ return;
+ }
+ switch(pass)
+ {
+ case LSCP_PRETTY_PRINT:
+ mExpression->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, "++");
+ break;
+ case LSCP_EMIT_ASSEMBLY:
+ {
+ mExpression->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ if (mReturnType == LST_INTEGER)
+ {
+ fprintf(fp, "PUSHARGI 1\n");
+ mExpression->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, "ADD integer, integer\n");
+ }
+ else if (mReturnType == LST_FLOATINGPOINT)
+ {
+ fprintf(fp, "PUSHARGF 1\n");
+ mExpression->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, "ADD float, float\n");
+ }
+ else
+ {
+ fprintf(fp, "Unexpected Type\n");
+ }
+ print_asignment(fp, mExpression);
+ fprintf(fp, "%s\n", LSCRIPTTypePop[mReturnType]);
+ }
+ break;
+ case LSCP_TYPE:
+ if (mExpression->mType != LET_LVALUE)
+ {
+ gErrorToText.writeError(fp, this, LSERROR_EXPRESSION_ON_LVALUE);
+ }
+ else
+ {
+ mExpression->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ if (!legal_unary_expression(type, type, mType))
+ {
+ gErrorToText.writeError(fp, this, LSERROR_TYPE_MISMATCH);
+ }
+ else
+ {
+ mReturnType = mLeftType = type;
+ }
+ }
+ break;
+ case LSCP_TO_STACK:
+ {
+ mExpression->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ if (mReturnType == LST_INTEGER)
+ {
+ chunk->addByte(LSCRIPTOpCodes[LOPC_PUSHARGI]);
+ chunk->addInteger(1);
+ mExpression->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ chunk->addByte(LSCRIPTOpCodes[LOPC_ADD]);
+ chunk->addByte(LSCRIPTTypeByte[LST_INTEGER] | LSCRIPTTypeHi4Bits[LST_INTEGER]);
+ }
+ else if (mReturnType == LST_FLOATINGPOINT)
+ {
+ chunk->addByte(LSCRIPTOpCodes[LOPC_PUSHARGF]);
+ chunk->addFloat(1.f);
+ mExpression->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ chunk->addByte(LSCRIPTOpCodes[LOPC_ADD]);
+ chunk->addByte(LSCRIPTTypeByte[LST_FLOATINGPOINT] | LSCRIPTTypeHi4Bits[LST_FLOATINGPOINT]);
+ }
+ store2stack(this, mExpression, chunk, mReturnType);
+ switch(mReturnType)
+ {
+ case LST_INTEGER:
+ case LST_FLOATINGPOINT:
+ chunk->addByte(LSCRIPTOpCodes[LOPC_POP]);
+ break;
+ case LST_KEY:
+ case LST_STRING:
+ chunk->addByte(LSCRIPTOpCodes[LOPC_POPS]);
+ break;
+ case LST_LIST:
+ chunk->addByte(LSCRIPTOpCodes[LOPC_POPL]);
+ break;
+ case LST_VECTOR:
+ chunk->addByte(LSCRIPTOpCodes[LOPC_POPV]);
+ break;
+ case LST_QUATERNION:
+ chunk->addByte(LSCRIPTOpCodes[LOPC_POPQ]);
+ break;
+ default:
+ chunk->addByte(LSCRIPTOpCodes[LOPC_POP]);
+ break;
+ }
+ }
+ break;
+ case LSCP_EMIT_CIL_ASSEMBLY:
+ {
+ print_cil_load_address(fp, mExpression, entry);
+ mExpression->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp,"dup\n"); // Copy expression result to use as increment operand.
+ if (mReturnType == LST_INTEGER)
+ {
+ fprintf(fp, "ldc.i4.1\n");
+ }
+ else if (mReturnType == LST_FLOATINGPOINT)
+ {
+ fprintf(fp, "ldc.r8.1\n");
+ }
+ else
+ {
+ fprintf(fp, "Unexpected Type\n");
+ }
+ fprintf(fp, "add\n");
+ print_cil_asignment(fp, mExpression, entry);
+ fprintf(fp, "pop\n"); // Pop assignment result to leave original expression result on stack. TODO: Optimise away redundant pop/dup pairs.
+ }
+ break;
+ default:
+ mExpression->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ break;
+ }
+ gonext(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+}
+
+S32 LLScriptPostIncrement::getSize()
+{
+ return 0;
+}
+
+void LLScriptPostDecrement::recurse(FILE *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)
+{
+ if (gErrorToText.getErrors())
+ {
+ return;
+ }
+ switch(pass)
+ {
+ case LSCP_PRETTY_PRINT:
+ mExpression->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, "--");
+ break;
+ case LSCP_EMIT_ASSEMBLY:
+ {
+ mExpression->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ if (mReturnType == LST_INTEGER)
+ {
+ fprintf(fp, "PUSHARGI 1\n");
+ mExpression->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, "SUB integer, integer\n");
+ }
+ else if (mReturnType == LST_FLOATINGPOINT)
+ {
+ fprintf(fp, "PUSHARGF 1\n");
+ mExpression->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, "SUB float, float\n");
+ }
+ else
+ {
+ fprintf(fp, "Unexpected Type\n");
+ }
+ print_asignment(fp, mExpression);
+ fprintf(fp, "%s\n", LSCRIPTTypePop[mReturnType]);
+ }
+ break;
+ case LSCP_TYPE:
+ if (mExpression->mType != LET_LVALUE)
+ {
+ gErrorToText.writeError(fp, this, LSERROR_EXPRESSION_ON_LVALUE);
+ }
+ else
+ {
+ mExpression->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ if (!legal_unary_expression(type, type, mType))
+ {
+ gErrorToText.writeError(fp, this, LSERROR_TYPE_MISMATCH);
+ }
+ else
+ {
+ mReturnType = mLeftType = type;
+ }
+ }
+ break;
+ case LSCP_TO_STACK:
+ {
+ mExpression->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ if (mReturnType == LST_INTEGER)
+ {
+ chunk->addByte(LSCRIPTOpCodes[LOPC_PUSHARGI]);
+ chunk->addInteger(1);
+ mExpression->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ chunk->addByte(LSCRIPTOpCodes[LOPC_SUB]);
+ chunk->addByte(LSCRIPTTypeByte[LST_INTEGER] | LSCRIPTTypeHi4Bits[LST_INTEGER]);
+ }
+ else if (mReturnType == LST_FLOATINGPOINT)
+ {
+ chunk->addByte(LSCRIPTOpCodes[LOPC_PUSHARGF]);
+ chunk->addFloat(1.f);
+ mExpression->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ chunk->addByte(LSCRIPTOpCodes[LOPC_SUB]);
+ chunk->addByte(LSCRIPTTypeByte[LST_FLOATINGPOINT] | LSCRIPTTypeHi4Bits[LST_FLOATINGPOINT]);
+ }
+ store2stack(this, mExpression, chunk, mReturnType);
+ switch(mReturnType)
+ {
+ case LST_INTEGER:
+ case LST_FLOATINGPOINT:
+ chunk->addByte(LSCRIPTOpCodes[LOPC_POP]);
+ break;
+ case LST_KEY:
+ case LST_STRING:
+ chunk->addByte(LSCRIPTOpCodes[LOPC_POPS]);
+ break;
+ case LST_LIST:
+ chunk->addByte(LSCRIPTOpCodes[LOPC_POPL]);
+ break;
+ case LST_VECTOR:
+ chunk->addByte(LSCRIPTOpCodes[LOPC_POPV]);
+ break;
+ case LST_QUATERNION:
+ chunk->addByte(LSCRIPTOpCodes[LOPC_POPQ]);
+ break;
+ default:
+ chunk->addByte(LSCRIPTOpCodes[LOPC_POP]);
+ break;
+ }
+ }
+ break;
+ case LSCP_EMIT_CIL_ASSEMBLY:
+ {
+ print_cil_load_address(fp, mExpression, entry);
+ mExpression->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp,"dup\n"); // Copy expression result to use as decrement operand.
+ if (mReturnType == LST_INTEGER)
+ {
+ fprintf(fp, "ldc.i4.1\n");
+ }
+ else if (mReturnType == LST_FLOATINGPOINT)
+ {
+ fprintf(fp, "ldc.r8.1\n");
+ }
+ else
+ {
+ fprintf(fp, "Unexpected Type\n");
+ }
+ fprintf(fp, "sub\n");
+ print_cil_asignment(fp, mExpression, entry);
+ fprintf(fp, "pop\n"); // Pop assignment result to leave original expression result on stack. TODO: Optimise away redundant pop/dup pairs.
+ }
+ break;
+ default:
+ mExpression->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ break;
+ }
+ gonext(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+}
+
+S32 LLScriptPostDecrement::getSize()
+{
+ return 0;
+}
+
+// Generate arg list.
+void print_cil_arg_list(FILE *fp, LLScriptFuncExpressionList* exp_list)
+{
+ // Print first argument.
+ print_cil_type(fp, exp_list->mFirstp->mReturnType);
+
+ // Recursively print next arguments.
+ if(exp_list->mSecondp != NULL)
+ {
+ fprintf(fp, ", ");
+ print_cil_arg_list(fp, (LLScriptFuncExpressionList*) exp_list->mSecondp);
+ }
+}
+
+void LLScriptFunctionCall::recurse(FILE *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)
+{
+ if (gErrorToText.getErrors())
+ {
+ return;
+ }
+ switch(pass)
+ {
+ case LSCP_PRETTY_PRINT:
+ mIdentifier->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, "( ");
+ if (mExpressionList)
+ mExpressionList->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, " )");
+ break;
+ case LSCP_EMIT_ASSEMBLY:
+ if (mIdentifier->mScopeEntry->mType)
+ fprintf(fp, "%s\n", LSCRIPTTypePush[mIdentifier->mScopeEntry->mType]);
+ fprintf(fp,"PUSHE\n");
+ fprintf(fp, "PUSHBP\n");
+ if (mExpressionList)
+ mExpressionList->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, mIdentifier->mScopeEntry, 0, NULL);
+ fprintf(fp, "PUSHARGE %d\n", mIdentifier->mScopeEntry->mSize - mIdentifier->mScopeEntry->mOffset);
+ fprintf(fp, "PUSHSP\n");
+ fprintf(fp, "PUSHARGI %d\n", mIdentifier->mScopeEntry->mSize);
+ fprintf(fp, "ADD integer, integer\n");
+ fprintf(fp, "POPBP\n");
+ if (mIdentifier->mScopeEntry->mIDType != LIT_LIBRARY_FUNCTION)
+ {
+ fprintf(fp, "CALL ");
+ mIdentifier->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ }
+ else
+ {
+ fprintf(fp, "CALLLID ");
+ mIdentifier->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, ", %d", (U32)mIdentifier->mScopeEntry->mLibraryNumber);
+ }
+ fprintf(fp, "\n");
+ fprintf(fp, "POPBP\n");
+ break;
+ case LSCP_SCOPE_PASS1:
+ if (mExpressionList)
+ mExpressionList->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ break;
+ case LSCP_SCOPE_PASS2:
+ {
+ LLScriptScopeEntry *entry = scope->findEntryTyped(mIdentifier->mName, LIT_FUNCTION);
+ if (!entry)
+ {
+ gErrorToText.writeError(fp, this, LSERROR_UNDEFINED_NAME);
+ }
+ else
+ {
+ // if we did find it, make sure this identifier is associated with the correct scope entry
+ mIdentifier->mScopeEntry = entry;
+ }
+ if (mExpressionList)
+ mExpressionList->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ }
+ break;
+ case LSCP_TYPE:
+ if (mIdentifier->mScopeEntry)
+ {
+ U64 argcount = 0;
+ if (mExpressionList)
+ mExpressionList->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, argcount, chunk, heap, stacksize, mIdentifier->mScopeEntry, 0, NULL);
+
+ if (!mIdentifier->mScopeEntry->mFunctionArgs.mString)
+ {
+ if (argcount)
+ {
+ gErrorToText.writeError(fp, this, LSERROR_FUNCTION_TYPE_ERROR);
+ }
+ }
+ else if (argcount != strlen(mIdentifier->mScopeEntry->mFunctionArgs.mString))
+ {
+ gErrorToText.writeError(fp, this, LSERROR_FUNCTION_TYPE_ERROR);
+ }
+ }
+
+ if (mIdentifier->mScopeEntry)
+ type = mIdentifier->mScopeEntry->mType;
+ else
+ type = LST_NULL;
+ mReturnType = type;
+ break;
+ case LSCP_TO_STACK:
+ switch(mIdentifier->mScopeEntry->mType)
+ {
+ case LST_INTEGER:
+ case LST_FLOATINGPOINT:
+ case LST_STRING:
+ case LST_KEY:
+ case LST_LIST:
+ chunk->addByte(LSCRIPTOpCodes[LOPC_PUSHE]);
+ break;
+ case LST_VECTOR:
+ chunk->addByte(LSCRIPTOpCodes[LOPC_PUSHEV]);
+ break;
+ case LST_QUATERNION:
+ chunk->addByte(LSCRIPTOpCodes[LOPC_PUSHEQ]);
+ break;
+ default:
+ break;
+ }
+ chunk->addByte(LSCRIPTOpCodes[LOPC_PUSHE]);
+ chunk->addByte(LSCRIPTOpCodes[LOPC_PUSHBP]);
+ if (mExpressionList)
+ {
+ // Don't let this change the count.
+ U64 dummy_count = 0;
+ mExpressionList->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, dummy_count, chunk, heap, stacksize, mIdentifier->mScopeEntry, 0, NULL);
+ //mExpressionList->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, mIdentifier->mScopeEntry, 0, NULL);
+ }
+ chunk->addByte(LSCRIPTOpCodes[LOPC_PUSHARGE]);
+ chunk->addInteger(mIdentifier->mScopeEntry->mSize - mIdentifier->mScopeEntry->mOffset);
+ chunk->addByte(LSCRIPTOpCodes[LOPC_PUSHSP]);
+ chunk->addByte(LSCRIPTOpCodes[LOPC_PUSHARGI]);
+ chunk->addInteger(mIdentifier->mScopeEntry->mSize);
+ chunk->addByte(LSCRIPTOpCodes[LOPC_ADD]);
+ chunk->addByte(LSCRIPTTypeByte[LST_INTEGER] | LSCRIPTTypeHi4Bits[LST_INTEGER]);
+ chunk->addByte(LSCRIPTOpCodes[LOPC_POPBP]);
+ if (mIdentifier->mScopeEntry->mIDType != LIT_LIBRARY_FUNCTION)
+ {
+ chunk->addByte(LSCRIPTOpCodes[LOPC_CALL]);
+ chunk->addInteger(mIdentifier->mScopeEntry->mCount);
+ }
+ else
+ {
+ chunk->addByte(LSCRIPTOpCodes[LOPC_CALLLIB_TWO_BYTE]);
+ chunk->addU16(mIdentifier->mScopeEntry->mLibraryNumber);
+ }
+ break;
+ case LSCP_EMIT_CIL_ASSEMBLY:
+ {
+ bool library_call = (mIdentifier->mScopeEntry->mIDType == LIT_LIBRARY_FUNCTION);
+ if(! library_call)
+ {
+ // Load this pointer.
+ fprintf(fp, "ldarg.0\n");
+ }
+
+ // Load args on to stack.
+ if (mExpressionList)
+ {
+ mExpressionList->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry /* Needed for is_parameter calls */, 0, NULL);
+ }
+
+ // Make call.
+ if (! library_call)
+ {
+ fprintf(fp, "callvirt instance ");
+ }
+ else
+ {
+ fprintf(fp, "call ");
+ }
+ print_cil_type(fp, mIdentifier->mScopeEntry->mType);
+ fprintf(fp, " class ");
+ if (library_call)
+ {
+ fprintf(fp, "[LScriptLibrary]LScriptLibrary");
+ }
+ else
+ {
+ fprintf(fp, "LSL");
+ }
+ fprintf(fp, "::");
+ mIdentifier->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, "(");
+ if (mExpressionList) {print_cil_arg_list(fp, (LLScriptFuncExpressionList*) mExpressionList);}
+ fprintf(fp, ")\n");
+ }
+ break;
+ default:
+ mIdentifier->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ if (mExpressionList)
+ mExpressionList->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ break;
+ }
+ gonext(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+}
+
+S32 LLScriptFunctionCall::getSize()
+{
+ return 0;
+}
+
+void LLScriptPrint::recurse(FILE *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)
+{
+ if (gErrorToText.getErrors())
+ {
+ return;
+ }
+ switch(pass)
+ {
+ case LSCP_PRETTY_PRINT:
+ fprintf(fp, " PRINT ( ");
+ mExpression->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, " )");
+ break;
+ case LSCP_EMIT_ASSEMBLY:
+ mExpression->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, "PRINT %s\n", LSCRIPTTypeNames[mLeftType]);
+ break;
+ case LSCP_TYPE:
+ mExpression->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mLeftType = type;
+ mReturnType = LST_NULL;
+ break;
+ case LSCP_TO_STACK:
+ mExpression->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ chunk->addByte(LSCRIPTOpCodes[LOPC_PRINT]);
+ chunk->addByte(LSCRIPTTypeByte[mLeftType]);
+ break;
+ default:
+ mExpression->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ break;
+ }
+ gonext(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+}
+
+S32 LLScriptPrint::getSize()
+{
+ return 0;
+}
+
+void LLScriptConstantExpression::recurse(FILE *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)
+{
+ if (gErrorToText.getErrors())
+ {
+ return;
+ }
+ switch(pass)
+ {
+ case LSCP_PRETTY_PRINT:
+ mConstant->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ break;
+ case LSCP_TYPE:
+ mConstant->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mReturnType = type;
+ break;
+ case LSCP_TO_STACK:
+ mConstant->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ break;
+ default:
+ mConstant->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ break;
+ }
+ gonext(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+}
+
+S32 LLScriptConstantExpression::getSize()
+{
+ return 0;
+}
+
+void LLScriptStatement::addStatement(LLScriptStatement *event)
+{
+ if (mNextp)
+ {
+ event->mNextp = mNextp;
+ }
+ mNextp = event;
+}
+
+void LLScriptStatement::recurse(FILE *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)
+{
+ fprintf(fp, "Statement Base Class -- should never get here!\n");
+}
+
+S32 LLScriptStatement::getSize()
+{
+ printf("Statement Base Class -- should never get here!\n");
+ return 0;
+}
+
+void LLScriptStatement::gonext(FILE *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)
+{
+ if (gErrorToText.getErrors())
+ {
+ return;
+ }
+ switch(pass)
+ {
+ case LSCP_PRETTY_PRINT:
+ if (mNextp)
+ {
+ fprintf(fp, ", ");
+ mNextp->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ }
+ break;
+ case LSCP_EMIT_ASSEMBLY:
+ if (mNextp)
+ {
+ mNextp->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ }
+ break;
+ default:
+ if (mNextp)
+ {
+ mNextp->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ }
+ break;
+ }
+}
+
+S32 LLScriptStatementSequence::getSize()
+{
+ return 0;
+}
+
+void LLScriptStatementSequence::recurse(FILE *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)
+{
+ if (gErrorToText.getErrors())
+ {
+ return;
+ }
+ switch(pass)
+ {
+ case LSCP_PRETTY_PRINT:
+ mFirstp->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mSecondp->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ break;
+ case LSCP_EMIT_ASSEMBLY:
+ mFirstp->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mSecondp->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ break;
+ case LSCP_PRUNE:
+ mFirstp->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ if (prunearg)
+ {
+ ptype = LSPRUNE_DEAD_CODE;
+ gErrorToText.writeWarning(fp, this, LSWARN_DEAD_CODE);
+ }
+ mSecondp->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ break;
+ case LSCP_TYPE:
+ // pass the return type into all statements so we can check returns
+ {
+ LSCRIPTType return_type = type;
+ mFirstp->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, return_type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ return_type = type;
+ mSecondp->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, return_type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ }
+ break;
+ default:
+ mFirstp->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mSecondp->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ break;
+ }
+ gonext(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+}
+
+S32 LLScriptNOOP::getSize()
+{
+ return 0;
+}
+
+void LLScriptNOOP::recurse(FILE *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)
+{
+ if (gErrorToText.getErrors())
+ {
+ return;
+ }
+ switch(pass)
+ {
+ case LSCP_PRETTY_PRINT:
+ fdotabs(fp, tabs, tabsize);
+ fprintf(fp, ";\n");
+ break;
+ case LSCP_PRUNE:
+ if (ptype == LSPRUNE_DEAD_CODE)
+ prunearg = TRUE;
+ else
+ prunearg = FALSE;
+ break;
+ default:
+ break;
+ }
+ gonext(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+}
+
+void add_exit_pops(LLScriptByteCodeChunk *chunk, LLScriptScopeEntry *entry)
+{
+ // remember that we need to pop in reverse order
+ S32 number, i;
+
+ if (entry->mLocals.mString)
+ {
+ number = (S32)strlen(entry->mLocals.mString);
+ for (i = number - 1; i >= 0; i--)
+ {
+ switch(entry->mLocals.getType(i))
+ {
+ case LST_INTEGER:
+ chunk->addByte(LSCRIPTOpCodes[LOPC_POP]);
+ break;
+ case LST_FLOATINGPOINT:
+ chunk->addByte(LSCRIPTOpCodes[LOPC_POP]);
+ break;
+ case LST_STRING:
+ case LST_KEY:
+ chunk->addByte(LSCRIPTOpCodes[LOPC_POPS]);
+ break;
+ case LST_VECTOR:
+ chunk->addByte(LSCRIPTOpCodes[LOPC_POPV]);
+ break;
+ case LST_QUATERNION:
+ chunk->addByte(LSCRIPTOpCodes[LOPC_POPQ]);
+ break;
+ case LST_LIST:
+ chunk->addByte(LSCRIPTOpCodes[LOPC_POPL]);
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
+
+ if (entry->mFunctionArgs.mString)
+ {
+ number = (S32)strlen(entry->mFunctionArgs.mString);
+ for (i = number - 1; i >= 0; i--)
+ {
+ switch(entry->mFunctionArgs.getType(i))
+ {
+ case LST_INTEGER:
+ chunk->addByte(LSCRIPTOpCodes[LOPC_POP]);
+ break;
+ case LST_FLOATINGPOINT:
+ chunk->addByte(LSCRIPTOpCodes[LOPC_POP]);
+ break;
+ case LST_STRING:
+ case LST_KEY:
+ chunk->addByte(LSCRIPTOpCodes[LOPC_POPS]);
+ break;
+ case LST_VECTOR:
+ chunk->addByte(LSCRIPTOpCodes[LOPC_POPV]);
+ break;
+ case LST_QUATERNION:
+ chunk->addByte(LSCRIPTOpCodes[LOPC_POPQ]);
+ break;
+ case LST_LIST:
+ chunk->addByte(LSCRIPTOpCodes[LOPC_POPL]);
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
+}
+
+void print_exit_pops(FILE *fp, LLScriptScopeEntry *entry)
+{
+ // remember that we need to pop in reverse order
+ S32 number, i;
+
+ if (entry->mLocals.mString)
+ {
+ number = (S32)strlen(entry->mLocals.mString);
+ for (i = number - 1; i >= 0; i--)
+ {
+ fprintf(fp, "%s", LSCRIPTTypePop[entry->mLocals.getType(i)]);
+ }
+ }
+
+ if (entry->mFunctionArgs.mString)
+ {
+ number = (S32)strlen(entry->mFunctionArgs.mString);
+ for (i = number - 1; i >= 0; i--)
+ {
+ fprintf(fp, "%s", LSCRIPTTypePop[entry->mFunctionArgs.getType(i)]);
+ }
+ }
+}
+
+
+S32 LLScriptStateChange::getSize()
+{
+ return 0;
+}
+
+void LLScriptStateChange::recurse(FILE *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)
+{
+ if (gErrorToText.getErrors())
+ {
+ return;
+ }
+ switch(pass)
+ {
+ case LSCP_PRETTY_PRINT:
+ fdotabs(fp, tabs, tabsize);
+ fprintf(fp, "state ");
+ mIdentifier->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, ";\n");
+ break;
+ case LSCP_EMIT_ASSEMBLY:
+ print_exit_pops(fp, entry);
+ fprintf(fp, "STATE ");
+ mIdentifier->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, "\n");
+ break;
+ case LSCP_PRUNE:
+ if ( (ptype == LSPRUNE_GLOBAL_VOIDS)
+ ||(ptype == LSPRUNE_GLOBAL_NON_VOIDS))
+ {
+ gErrorToText.writeError(fp, this, LSERROR_STATE_CHANGE_IN_GLOBAL);
+ }
+ if (ptype == LSPRUNE_DEAD_CODE)
+ prunearg = TRUE;
+ else
+ prunearg = FALSE;
+ break;
+ case LSCP_SCOPE_PASS2:
+ {
+ LLScriptScopeEntry *entry = scope->findEntryTyped(mIdentifier->mName, LIT_STATE);
+ if (!entry)
+ {
+ gErrorToText.writeError(fp, this, LSERROR_UNDEFINED_NAME);
+ }
+ else
+ {
+ // if we did find it, make sure this identifier is associated with the correct scope entry
+ mIdentifier->mScopeEntry = entry;
+ }
+ }
+ break;
+ case LSCP_EMIT_BYTE_CODE:
+ {
+ add_exit_pops(chunk, entry);
+ chunk->addByte(LSCRIPTOpCodes[LOPC_STATE]);
+ chunk->addInteger(mIdentifier->mScopeEntry->mCount);
+ }
+ break;
+ case LSCP_EMIT_CIL_ASSEMBLY:
+ fprintf(fp, "ldstr \"");
+ mIdentifier->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, "\"\n");
+ fprintf(fp, "call void class [LScriptLibrary]LScriptInternal::change_state(string)\n");
+ break;
+ default:
+ mIdentifier->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ break;
+ }
+ gonext(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+}
+
+S32 LLScriptJump::getSize()
+{
+ return 0;
+}
+
+void LLScriptJump::recurse(FILE *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)
+{
+ if (gErrorToText.getErrors())
+ {
+ return;
+ }
+ switch(pass)
+ {
+ case LSCP_PRETTY_PRINT:
+ fdotabs(fp, tabs, tabsize);
+ fprintf(fp, "jump ");
+ mIdentifier->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, ";\n");
+ break;
+ case LSCP_EMIT_ASSEMBLY:
+ fprintf(fp, "JUMP ");
+ mIdentifier->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, "\n");
+ break;
+ case LSCP_PRUNE:
+ if (ptype == LSPRUNE_DEAD_CODE)
+ prunearg = TRUE;
+ else
+ prunearg = FALSE;
+ break;
+ case LSCP_SCOPE_PASS2:
+ {
+ LLScriptScopeEntry *entry = scope->findEntryTyped(mIdentifier->mName, LIT_LABEL);
+ if (!entry)
+ {
+ gErrorToText.writeError(fp, this, LSERROR_UNDEFINED_NAME);
+ }
+ else
+ {
+ // if we did find it, make sure this identifier is associated with the correct scope entry
+ mIdentifier->mScopeEntry = entry;
+ }
+ }
+ break;
+ case LSCP_EMIT_BYTE_CODE:
+ {
+ chunk->addByte(LSCRIPTOpCodes[LOPC_JUMP]);
+ chunk->addBytes(LSCRIPTDataSize[LST_INTEGER]);
+ chunk->addJump(mIdentifier->mName);
+ }
+ break;
+ case LSCP_EMIT_CIL_ASSEMBLY:
+ fprintf(fp, "br ");
+ mIdentifier->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, "\n");
+ break;
+ default:
+ mIdentifier->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ break;
+ }
+ gonext(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+}
+
+S32 LLScriptLabel::getSize()
+{
+ return 0;
+}
+
+void LLScriptLabel::recurse(FILE *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)
+{
+ if (gErrorToText.getErrors())
+ {
+ return;
+ }
+ switch(pass)
+ {
+ case LSCP_PRETTY_PRINT:
+ fdotabs(fp, tabs, tabsize);
+ fprintf(fp, "@");
+ mIdentifier->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, ";\n");
+ break;
+ case LSCP_EMIT_ASSEMBLY:
+ fprintf(fp, "LABEL ");
+ mIdentifier->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, "\n");
+ break;
+ case LSCP_PRUNE:
+ // Always clear this flag, to stop pruning after return statements. A jump
+ // might start up code at this label, so we need to stop pruning.
+ prunearg = FALSE;
+ break;
+ case LSCP_SCOPE_PASS1:
+ // add labels to scope
+ if (scope->checkEntry(mIdentifier->mName))
+ {
+ gErrorToText.writeError(fp, this, LSERROR_DUPLICATE_NAME);
+ }
+ else
+ {
+ mIdentifier->mScopeEntry = scope->addEntry(mIdentifier->mName, LIT_LABEL, LST_NULL);
+ }
+ break;
+ case LSCP_EMIT_BYTE_CODE:
+ {
+ chunk->addLabel(mIdentifier->mName);
+ }
+ break;
+ case LSCP_EMIT_CIL_ASSEMBLY:
+ mIdentifier->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, ":\n");
+ break;
+ default:
+ mIdentifier->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ break;
+ }
+ gonext(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+}
+
+void add_return(LLScriptByteCodeChunk *chunk, LLScriptScopeEntry *entry)
+{
+ add_exit_pops(chunk, entry);
+ chunk->addByte(LSCRIPTOpCodes[LOPC_RETURN]);
+}
+
+void print_return(FILE *fp, LLScriptScopeEntry *entry)
+{
+ print_exit_pops(fp, entry);
+ fprintf(fp, "RETURN\n");
+}
+
+
+S32 LLScriptReturn::getSize()
+{
+ return 0;
+}
+
+void LLScriptReturn::recurse(FILE *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)
+{
+ if (gErrorToText.getErrors())
+ {
+ return;
+ }
+ switch(pass)
+ {
+ case LSCP_PRETTY_PRINT:
+ if (mExpression)
+ {
+ fdotabs(fp, tabs, tabsize);
+ fprintf(fp, "return ");
+ mExpression->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, ";\n");
+ }
+ else
+ {
+ fdotabs(fp, tabs, tabsize);
+ fprintf(fp, "return;\n");
+ }
+ break;
+ case LSCP_EMIT_ASSEMBLY:
+ if (mExpression)
+ {
+ mExpression->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, "%s\n", LSCRIPTTypeReturn[mType]);
+ }
+ print_return(fp, entry);
+ break;
+ case LSCP_PRUNE:
+ if ( (ptype == LSPRUNE_GLOBAL_VOIDS)
+ ||(ptype == LSPRUNE_EVENTS))
+ {
+ if (mExpression)
+ {
+ gErrorToText.writeError(fp, this, LSERROR_INVALID_RETURN);
+ }
+ }
+ else if (ptype == LSPRUNE_GLOBAL_NON_VOIDS)
+ {
+ if (!mExpression)
+ {
+ gErrorToText.writeError(fp, this, LSERROR_INVALID_VOID_RETURN);
+ }
+ }
+ prunearg = TRUE;
+ case LSCP_TYPE:
+ // if there is a return expression, it must be promotable to the return type of the function
+ if (mExpression)
+ {
+ mExpression->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ if (!legal_assignment(basetype, type))
+ {
+ gErrorToText.writeError(fp, this, LSERROR_TYPE_MISMATCH);
+ }
+ else
+ {
+ mType = basetype;
+ }
+ }
+ break;
+ case LSCP_EMIT_BYTE_CODE:
+ if (mExpression)
+ {
+ mExpression->recurse(fp, tabs, tabsize, LSCP_TO_STACK, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ switch(mType)
+ {
+ case LST_INTEGER:
+ case LST_FLOATINGPOINT:
+ chunk->addByte(LSCRIPTOpCodes[LOPC_LOADP]);
+ chunk->addInteger(-12);
+ break;
+ case LST_STRING:
+ case LST_KEY:
+ // use normal store for reference counted types
+ chunk->addByte(LSCRIPTOpCodes[LOPC_LOADSP]);
+ chunk->addInteger(-12);
+ break;
+ case LST_LIST:
+ // use normal store for reference counted types
+ chunk->addByte(LSCRIPTOpCodes[LOPC_LOADLP]);
+ chunk->addInteger(-12);
+ break;
+ case LST_VECTOR:
+ chunk->addByte(LSCRIPTOpCodes[LOPC_LOADVP]);
+ chunk->addInteger(-20);
+ break;
+ case LST_QUATERNION:
+ chunk->addByte(LSCRIPTOpCodes[LOPC_LOADQP]);
+ chunk->addInteger(-24);
+ break;
+ default:
+ chunk->addByte(LSCRIPTOpCodes[LOPC_LOADP]);
+ chunk->addInteger(-12);
+ break;
+ }
+ }
+ add_return(chunk, entry);
+ break;
+ case LSCP_EMIT_CIL_ASSEMBLY:
+ if (mExpression)
+ {
+ mExpression->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ }
+ fprintf(fp, "ret\n");
+ break;
+ default:
+ if (mExpression)
+ {
+ mExpression->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ }
+ break;
+ }
+ gonext(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+}
+
+S32 LLScriptExpressionStatement::getSize()
+{
+ return 0;
+}
+
+void LLScriptExpressionStatement::recurse(FILE *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)
+{
+ if (gErrorToText.getErrors())
+ {
+ return;
+ }
+ switch(pass)
+ {
+ case LSCP_PRETTY_PRINT:
+ fdotabs(fp, tabs, tabsize);
+ mExpression->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, ";\n");
+ break;
+ case LSCP_EMIT_ASSEMBLY:
+ mExpression->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ if (mExpression->mReturnType)
+ {
+ fprintf(fp, "%s\n", LSCRIPTTypePop[mExpression->mReturnType]);
+ }
+ break;
+ case LSCP_PRUNE:
+ if (ptype == LSPRUNE_DEAD_CODE)
+ prunearg = TRUE;
+ else
+ prunearg = FALSE;
+ break;
+ case LSCP_EMIT_BYTE_CODE:
+ mExpression->recurse(fp, tabs, tabsize, LSCP_TO_STACK, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ switch(mExpression->mReturnType)
+ {
+ case LST_INTEGER:
+ case LST_FLOATINGPOINT:
+ chunk->addByte(LSCRIPTOpCodes[LOPC_POP]);
+ break;
+ case LST_STRING:
+ case LST_KEY:
+ chunk->addByte(LSCRIPTOpCodes[LOPC_POPS]);
+ break;
+ case LST_LIST:
+ chunk->addByte(LSCRIPTOpCodes[LOPC_POPL]);
+ break;
+ case LST_VECTOR:
+ chunk->addByte(LSCRIPTOpCodes[LOPC_POPV]);
+ break;
+ case LST_QUATERNION:
+ chunk->addByte(LSCRIPTOpCodes[LOPC_POPQ]);
+ break;
+ default:
+ break;
+ }
+ break;
+ case LSCP_EMIT_CIL_ASSEMBLY:
+ mExpression->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ if(mExpression->mReturnType)
+ {
+ fprintf(fp, "pop\n");
+ }
+ break;
+ default:
+ mExpression->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ break;
+ }
+ gonext(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+}
+
+S32 LLScriptIf::getSize()
+{
+ return 0;
+}
+
+void LLScriptIf::recurse(FILE *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)
+{
+ if (gErrorToText.getErrors())
+ {
+ return;
+ }
+ switch(pass)
+ {
+ case LSCP_PRETTY_PRINT:
+ fdotabs(fp, tabs, tabsize);
+ fprintf(fp, "if ( ");
+ mExpression->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, " )\n");
+ mStatement->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ break;
+ case LSCP_EMIT_ASSEMBLY:
+ {
+ S32 tjump = gTempJumpCount++;
+ mExpression->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, "JUMPNIF ##Temp Jump %d##\n", tjump);
+ mStatement->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, "LABEL ##Temp Jump %d##\n", tjump);
+ }
+ break;
+ case LSCP_PRUNE:
+ if (ptype == LSPRUNE_DEAD_CODE)
+ prunearg = TRUE;
+ else
+ prunearg = FALSE;
+ break;
+ case LSCP_TYPE:
+ mExpression->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mType = type;
+ mStatement->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ break;
+ case LSCP_EMIT_BYTE_CODE:
+ {
+ char jumpname[32];
+ sprintf(jumpname, "##Temp Jump %d##", gTempJumpCount++);
+
+ mExpression->recurse(fp, tabs, tabsize, LSCP_TO_STACK, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ chunk->addByte(LSCRIPTOpCodes[LOPC_JUMPNIF]);
+ chunk->addByte(LSCRIPTTypeByte[mType]);
+ chunk->addBytes(LSCRIPTDataSize[LST_INTEGER]);
+ chunk->addJump(jumpname);
+ mStatement->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ chunk->addLabel(jumpname);
+ }
+ break;
+ case LSCP_EMIT_CIL_ASSEMBLY:
+ {
+ S32 tjump = gTempJumpCount++;
+ mExpression->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, "brfalse LabelTempJump%d\n", tjump);
+ mStatement->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, "LabelTempJump%d:\n", tjump);
+ }
+ break;
+ default:
+ mExpression->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mStatement->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ break;
+ }
+ gonext(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+}
+
+S32 LLScriptIfElse::getSize()
+{
+ return 0;
+}
+
+void LLScriptIfElse::recurse(FILE *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)
+{
+ if (gErrorToText.getErrors())
+ {
+ return;
+ }
+ switch(pass)
+ {
+ case LSCP_PRETTY_PRINT:
+ fdotabs(fp, tabs, tabsize);
+ fprintf(fp, "if ( ");
+ mExpression->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, " )\n");
+ mStatement1->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fdotabs(fp, tabs, tabsize);
+ fprintf(fp, "else\n");
+ mStatement2->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ break;
+ case LSCP_EMIT_ASSEMBLY:
+ {
+ S32 tjump1 = gTempJumpCount++;
+ S32 tjump2 = gTempJumpCount++;
+ mExpression->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, "JUMPNIF ##Temp Jump %d##\n", tjump1);
+ mStatement1->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, "JUMP ##Temp Jump %d##\n", tjump2);
+ fprintf(fp, "LABEL ##Temp Jump %d##\n", tjump1);
+ mStatement2->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, "LABEL ##Temp Jump %d##\n", tjump2);
+ }
+ break;
+ case LSCP_PRUNE:
+ {
+ BOOL arg1 = TRUE, arg2 = TRUE;
+ mStatement1->recurse(fp, tabs, tabsize, pass, ptype, arg1, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mStatement2->recurse(fp, tabs, tabsize, pass, ptype, arg2, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ prunearg = arg1 && arg2;
+ }
+ break;
+ case LSCP_TYPE:
+ mExpression->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mType = type;
+ mStatement1->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mStatement2->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ break;
+ case LSCP_EMIT_BYTE_CODE:
+ {
+ char jumpname1[32];
+ sprintf(jumpname1, "##Temp Jump %d##", gTempJumpCount++);
+ char jumpname2[32];
+ sprintf(jumpname2, "##Temp Jump %d##", gTempJumpCount++);
+
+ mExpression->recurse(fp, tabs, tabsize, LSCP_TO_STACK, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ chunk->addByte(LSCRIPTOpCodes[LOPC_JUMPNIF]);
+ chunk->addByte(LSCRIPTTypeByte[mType]);
+ chunk->addBytes(LSCRIPTDataSize[LST_INTEGER]);
+ chunk->addJump(jumpname1);
+ mStatement1->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ chunk->addByte(LSCRIPTOpCodes[LOPC_JUMP]);
+ chunk->addBytes(LSCRIPTDataSize[LST_INTEGER]);
+ chunk->addJump(jumpname2);
+ chunk->addLabel(jumpname1);
+ mStatement2->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ chunk->addLabel(jumpname2);
+ }
+ break;
+ case LSCP_EMIT_CIL_ASSEMBLY:
+ {
+ S32 tjump1 = gTempJumpCount++;
+ S32 tjump2 = gTempJumpCount++;
+ mExpression->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, "brfalse LabelTempJump%d\n", tjump1);
+ mStatement1->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, "br LabelTempJump%d\n", tjump2);
+ fprintf(fp, "LabelTempJump%d:\n", tjump1);
+ mStatement2->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, "LabelTempJump%d:\n", tjump2);
+ }
+ break;
+ default:
+ mExpression->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mStatement1->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mStatement2->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ break;
+ };
+ gonext(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+}
+
+S32 LLScriptFor::getSize()
+{
+ return 0;
+}
+
+void LLScriptFor::recurse(FILE *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)
+{
+ if (gErrorToText.getErrors())
+ {
+ return;
+ }
+ switch(pass)
+ {
+ case LSCP_PRETTY_PRINT:
+ fdotabs(fp, tabs, tabsize);
+ fprintf(fp, "for ( ");
+ if(mSequence)
+ mSequence->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, " ; ");
+ mExpression->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, " ; ");
+ if(mExpressionList)
+ mExpressionList->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, " )\n");
+ if(mStatement)
+ mStatement->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ break;
+ case LSCP_EMIT_ASSEMBLY:
+ {
+ S32 tjump1 = gTempJumpCount++;
+ S32 tjump2 = gTempJumpCount++;
+ if(mSequence)
+ mSequence->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, "LABEL ##Temp Jump %d##\n", tjump1);
+ mExpression->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, "JUMPNIF ##Temp Jump %d##\n", tjump2);
+ if(mStatement)
+ mStatement->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ if(mExpressionList)
+ mExpressionList->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, "JUMP ##Temp Jump %d##\n", tjump1);
+ fprintf(fp, "LABEL ##Temp Jump %d##\n", tjump2);
+ }
+ break;
+ case LSCP_PRUNE:
+ if (ptype == LSPRUNE_DEAD_CODE)
+ prunearg = TRUE;
+ else
+ prunearg = FALSE;
+ break;
+ case LSCP_TYPE:
+ if(mSequence)
+ mSequence->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mExpression->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mType = type;
+ if(mExpressionList)
+ mExpressionList->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ if(mStatement)
+ mStatement->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ break;
+ case LSCP_EMIT_BYTE_CODE:
+ {
+ char jumpname1[32];
+ sprintf(jumpname1, "##Temp Jump %d##", gTempJumpCount++);
+ char jumpname2[32];
+ sprintf(jumpname2, "##Temp Jump %d##", gTempJumpCount++);
+
+ if(mSequence)
+ mSequence->recurse(fp, tabs, tabsize, LSCP_TO_STACK, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ chunk->addLabel(jumpname1);
+ mExpression->recurse(fp, tabs, tabsize, LSCP_TO_STACK, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ chunk->addByte(LSCRIPTOpCodes[LOPC_JUMPNIF]);
+ chunk->addByte(LSCRIPTTypeByte[mType]);
+ chunk->addBytes(LSCRIPTDataSize[LST_INTEGER]);
+ chunk->addJump(jumpname2);
+ if(mStatement)
+ mStatement->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ if(mExpressionList)
+ mExpressionList->recurse(fp, tabs, tabsize, LSCP_TO_STACK, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ chunk->addByte(LSCRIPTOpCodes[LOPC_JUMP]);
+ chunk->addBytes(LSCRIPTDataSize[LST_INTEGER]);
+ chunk->addJump(jumpname1);
+ chunk->addLabel(jumpname2);
+ }
+ break;
+ case LSCP_EMIT_CIL_ASSEMBLY:
+ {
+ S32 tjump1 = gTempJumpCount++;
+ S32 tjump2 = gTempJumpCount++;
+ if(mSequence)
+ mSequence->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, "LabelTempJump%d:\n", tjump1);
+ mExpression->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, "brfalse LabelTempJump%d\n", tjump2);
+ if(mStatement)
+ mStatement->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ if(mExpressionList)
+ mExpressionList->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, "br LabelTempJump%d\n", tjump1);
+ fprintf(fp, "LabelTempJump%d:\n", tjump2);
+ }
+ break;
+ default:
+ if(mSequence)
+ mSequence->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mExpression->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ if(mExpressionList)
+ mExpressionList->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ if(mStatement)
+ mStatement->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ break;
+ }
+ gonext(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+}
+
+S32 LLScriptDoWhile::getSize()
+{
+ return 0;
+}
+
+void LLScriptDoWhile::recurse(FILE *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)
+{
+ if (gErrorToText.getErrors())
+ {
+ return;
+ }
+ switch(pass)
+ {
+ case LSCP_PRETTY_PRINT:
+ fdotabs(fp, tabs, tabsize);
+ fprintf(fp, "do\n");
+ mStatement->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fdotabs(fp, tabs, tabsize);
+ fprintf(fp, "while( ");
+ mExpression->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, " );\n");
+ break;
+ case LSCP_EMIT_ASSEMBLY:
+ {
+ S32 tjump1 = gTempJumpCount++;
+ fprintf(fp, "LABEL ##Temp Jump %d##\n", tjump1);
+ mStatement->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mExpression->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, "JUMPIF ##Temp Jump %d##\n", tjump1);
+ }
+ break;
+ case LSCP_PRUNE:
+ if (ptype == LSPRUNE_DEAD_CODE)
+ prunearg = TRUE;
+ else
+ prunearg = FALSE;
+ break;
+ case LSCP_TYPE:
+ mStatement->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mExpression->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mType = type;
+ break;
+ case LSCP_EMIT_BYTE_CODE:
+ {
+ char jumpname1[32];
+ sprintf(jumpname1, "##Temp Jump %d##", gTempJumpCount++);
+
+ chunk->addLabel(jumpname1);
+ mStatement->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mExpression->recurse(fp, tabs, tabsize, LSCP_TO_STACK, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ chunk->addByte(LSCRIPTOpCodes[LOPC_JUMPIF]);
+ chunk->addByte(LSCRIPTTypeByte[mType]);
+ chunk->addBytes(LSCRIPTDataSize[LST_INTEGER]);
+ chunk->addJump(jumpname1);
+ }
+ break;
+ case LSCP_EMIT_CIL_ASSEMBLY:
+ {
+ S32 tjump1 = gTempJumpCount++;
+ fprintf(fp, "LabelTempJump%d:\n", tjump1);
+ mStatement->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mExpression->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, "brtrue LabelTempJump%d\n", tjump1);
+ }
+ break;
+ default:
+ mStatement->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mExpression->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ break;
+ }
+ gonext(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+}
+
+S32 LLScriptWhile::getSize()
+{
+ return 0;
+}
+
+void LLScriptWhile::recurse(FILE *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)
+{
+ if (gErrorToText.getErrors())
+ {
+ return;
+ }
+ switch(pass)
+ {
+ case LSCP_PRETTY_PRINT:
+ fdotabs(fp, tabs, tabsize);
+ fprintf(fp, "while( ");
+ mExpression->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, " )\n");
+ mStatement->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ break;
+ case LSCP_EMIT_ASSEMBLY:
+ {
+ S32 tjump1 = gTempJumpCount++;
+ S32 tjump2 = gTempJumpCount++;
+ fprintf(fp, "LABEL ##Temp Jump %d##\n", tjump1);
+ mExpression->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, "JUMPNIF ##Temp Jump %d##\n", tjump2);
+ mStatement->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, "JUMP ##Temp Jump %d##\n", tjump1);
+ fprintf(fp, "LABEL ##Temp Jump %d##\n", tjump2);
+ }
+ break;
+ case LSCP_PRUNE:
+ if (ptype == LSPRUNE_DEAD_CODE)
+ prunearg = TRUE;
+ else
+ prunearg = FALSE;
+ break;
+ case LSCP_TYPE:
+ mExpression->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mType = type;
+ mStatement->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ break;
+ case LSCP_EMIT_BYTE_CODE:
+ {
+ char jumpname1[32];
+ sprintf(jumpname1, "##Temp Jump %d##", gTempJumpCount++);
+ char jumpname2[32];
+ sprintf(jumpname2, "##Temp Jump %d##", gTempJumpCount++);
+
+ chunk->addLabel(jumpname1);
+ mExpression->recurse(fp, tabs, tabsize, LSCP_TO_STACK, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ chunk->addByte(LSCRIPTOpCodes[LOPC_JUMPNIF]);
+ chunk->addByte(LSCRIPTTypeByte[mType]);
+ chunk->addBytes(LSCRIPTDataSize[LST_INTEGER]);
+ chunk->addJump(jumpname2);
+ mStatement->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ chunk->addByte(LSCRIPTOpCodes[LOPC_JUMP]);
+ chunk->addBytes(LSCRIPTDataSize[LST_INTEGER]);
+ chunk->addJump(jumpname1);
+ chunk->addLabel(jumpname2);
+ }
+ break;
+ case LSCP_EMIT_CIL_ASSEMBLY:
+ {
+ S32 tjump1 = gTempJumpCount++;
+ S32 tjump2 = gTempJumpCount++;
+ fprintf(fp, "LabelTempJump%d:\n", tjump1);
+ mExpression->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, "brfalse LabelTempJump%d\n", tjump2);
+ mStatement->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, "br LabelTempJump%d\n", tjump1);
+ fprintf(fp, "LabelTempJump%d:\n", tjump2);
+ }
+ break;
+ default:
+ mExpression->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mStatement->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ break;
+ }
+ gonext(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+}
+
+S32 LLScriptDeclaration::getSize()
+{
+ return mType->getSize();
+}
+
+void LLScriptDeclaration::recurse(FILE *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)
+{
+ if (gErrorToText.getErrors())
+ {
+ return;
+ }
+ switch(pass)
+ {
+ case LSCP_PRETTY_PRINT:
+ if (mExpression)
+ {
+ fdotabs(fp, tabs, tabsize);
+ mType->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, "\t");
+ mIdentifier->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, " = ");
+ mExpression->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, ";\n");
+ }
+ else
+ {
+ fdotabs(fp, tabs, tabsize);
+ mType->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, "\t");
+ mIdentifier->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, ";\n");
+ }
+ break;
+ case LSCP_EMIT_ASSEMBLY:
+ if (mExpression)
+ {
+ mExpression->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ if (mIdentifier->mScopeEntry->mIDType == LIT_VARIABLE)
+ {
+ fprintf(fp, "%s%d [%s]\n", LSCRIPTTypeLocalDeclaration[mIdentifier->mScopeEntry->mType], mIdentifier->mScopeEntry->mOffset, mIdentifier->mName);
+ }
+ else if (mIdentifier->mScopeEntry->mIDType == LIT_GLOBAL)
+ {
+ gErrorToText.writeError(fp, this, LSERROR_UNDEFINED_NAME);
+ }
+ }
+ break;
+ case LSCP_PRUNE:
+ if (ptype == LSPRUNE_DEAD_CODE)
+ prunearg = TRUE;
+ else
+ prunearg = FALSE;
+ break;
+ case LSCP_SCOPE_PASS1:
+ // Check to see if a declaration is valid here.
+ if (!mAllowDeclarations)
+ {
+ gErrorToText.writeError(fp, this, LSERROR_NEED_NEW_SCOPE);
+ }
+ // add labels to scope
+ else if (scope->checkEntry(mIdentifier->mName))
+ {
+ gErrorToText.writeError(fp, this, LSERROR_DUPLICATE_NAME);
+ }
+ else
+ {
+ if (mExpression)
+ {
+ mExpression->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ }
+ // this needs to go after expression decent to make sure that we don't add ourselves or something silly
+ // check expression if it exists
+ mIdentifier->mScopeEntry = scope->addEntry(mIdentifier->mName, LIT_VARIABLE, mType->mType);
+ }
+ break;
+ case LSCP_TYPE:
+ // if there is an expression, it must be promotable to variable type
+ if (mExpression && mIdentifier->mScopeEntry)
+ {
+ mExpression->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ if (!legal_assignment(mIdentifier->mScopeEntry->mType, type))
+ {
+ gErrorToText.writeError(fp, this, LSERROR_TYPE_MISMATCH);
+ }
+ }
+ break;
+ case LSCP_RESOURCE:
+ {
+ mIdentifier->mScopeEntry->mOffset = (S32)count;
+ mIdentifier->mScopeEntry->mSize = mType->getSize();
+ count += mIdentifier->mScopeEntry->mSize;
+ // Index into locals is current number of locals. Stored in mCount member of mScopeEntry.
+ mIdentifier->mScopeEntry->mCount = entry->mLocals.getNumber();
+ entry->mLocals.addType(mType->mType);
+ mIdentifier->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ }
+ break;
+ case LSCP_EMIT_BYTE_CODE:
+ if (mExpression)
+ {
+ mExpression->recurse(fp, tabs, tabsize, LSCP_TO_STACK, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ if (mExpression->mReturnType != mIdentifier->mScopeEntry->mType)
+ {
+ cast2stack(chunk, mExpression->mReturnType, mIdentifier->mScopeEntry->mType);
+ }
+ switch(mExpression->mReturnType)
+ {
+ case LST_INTEGER:
+ case LST_FLOATINGPOINT:
+ if (mIdentifier->mScopeEntry->mIDType == LIT_VARIABLE)
+ {
+ chunk->addByte(LSCRIPTOpCodes[LOPC_LOADP]);
+ }
+ break;
+ case LST_STRING:
+ case LST_KEY:
+ if (mIdentifier->mScopeEntry->mIDType == LIT_VARIABLE)
+ {
+ chunk->addByte(LSCRIPTOpCodes[LOPC_LOADSP]);
+ }
+ break;
+ case LST_LIST:
+ if (mIdentifier->mScopeEntry->mIDType == LIT_VARIABLE)
+ {
+ chunk->addByte(LSCRIPTOpCodes[LOPC_LOADLP]);
+ }
+ break;
+ case LST_VECTOR:
+ if (mIdentifier->mScopeEntry->mIDType == LIT_VARIABLE)
+ {
+ chunk->addByte(LSCRIPTOpCodes[LOPC_LOADVP]);
+ }
+ break;
+ case LST_QUATERNION:
+ if (mIdentifier->mScopeEntry->mIDType == LIT_VARIABLE)
+ {
+ chunk->addByte(LSCRIPTOpCodes[LOPC_LOADQP]);
+ }
+ break;
+ default:
+ if (mIdentifier->mScopeEntry->mIDType == LIT_VARIABLE)
+ {
+ chunk->addByte(LSCRIPTOpCodes[LOPC_LOADP]);
+ }
+ break;
+ }
+ if (mIdentifier->mScopeEntry->mIDType == LIT_VARIABLE)
+ {
+ S32 address = mIdentifier->mScopeEntry->mOffset;
+ chunk->addInteger(address);
+ }
+ }
+ else
+ {
+ switch(mIdentifier->mScopeEntry->mType)
+ {
+ case LST_INTEGER:
+ case LST_FLOATINGPOINT:
+ if (mIdentifier->mScopeEntry->mIDType == LIT_VARIABLE)
+ {
+ chunk->addByte(LSCRIPTOpCodes[LOPC_PUSHARGI]);
+ chunk->addInteger(0);
+ chunk->addByte(LSCRIPTOpCodes[LOPC_LOADP]);
+ }
+ break;
+ case LST_STRING:
+ case LST_KEY:
+ if (mIdentifier->mScopeEntry->mIDType == LIT_VARIABLE)
+ {
+ chunk->addByte(LSCRIPTOpCodes[LOPC_PUSHARGS]);
+ chunk->addBytes("", 1);
+ chunk->addByte(LSCRIPTOpCodes[LOPC_LOADSP]);
+ }
+ break;
+ case LST_LIST:
+ if (mIdentifier->mScopeEntry->mIDType == LIT_VARIABLE)
+ {
+ chunk->addByte(LSCRIPTOpCodes[LOPC_STACKTOL]);
+ chunk->addInteger(0);
+ chunk->addByte(LSCRIPTOpCodes[LOPC_LOADLP]);
+ }
+ break;
+ case LST_VECTOR:
+ if (mIdentifier->mScopeEntry->mIDType == LIT_VARIABLE)
+ {
+ chunk->addByte(LSCRIPTOpCodes[LOPC_PUSHARGV]);
+ chunk->addFloat(0);
+ chunk->addFloat(0);
+ chunk->addFloat(0);
+ chunk->addByte(LSCRIPTOpCodes[LOPC_LOADVP]);
+ }
+ break;
+ case LST_QUATERNION:
+ if (mIdentifier->mScopeEntry->mIDType == LIT_VARIABLE)
+ {
+ chunk->addByte(LSCRIPTOpCodes[LOPC_PUSHARGQ]);
+ chunk->addFloat(1);
+ chunk->addFloat(0);
+ chunk->addFloat(0);
+ chunk->addFloat(0);
+ chunk->addByte(LSCRIPTOpCodes[LOPC_LOADQP]);
+ }
+ break;
+ default:
+ if (mIdentifier->mScopeEntry->mIDType == LIT_VARIABLE)
+ {
+ chunk->addByte(LSCRIPTOpCodes[LOPC_PUSHARGI]);
+ chunk->addInteger(0);
+ chunk->addByte(LSCRIPTOpCodes[LOPC_LOADP]);
+ }
+ break;
+ }
+ if (mIdentifier->mScopeEntry->mIDType == LIT_VARIABLE)
+ {
+ S32 address = mIdentifier->mScopeEntry->mOffset;
+ chunk->addInteger(address);
+ }
+ }
+ break;
+ case LSCP_EMIT_CIL_ASSEMBLY:
+ if (mExpression)
+ {
+ mExpression->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ if (mIdentifier->mScopeEntry->mIDType == LIT_VARIABLE)
+ {
+ if(is_parameter(mIdentifier, entry))
+ {
+ // Parameter, store by name.
+ fprintf(fp, "starg.s %s\n", mIdentifier->mScopeEntry->mIdentifier);
+ }
+ else
+ {
+ // Local, store by index.
+ fprintf(fp, "stloc.s %d\n", mIdentifier->mScopeEntry->mCount);
+ }
+ }
+ else if (mIdentifier->mScopeEntry->mIDType == LIT_GLOBAL)
+ {
+ gErrorToText.writeError(fp, this, LSERROR_UNDEFINED_NAME);
+ }
+ }
+ break;
+ default:
+ if (mExpression)
+ {
+ mType->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mIdentifier->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mExpression->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ }
+ else
+ {
+ mType->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mIdentifier->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ }
+ break;
+ }
+ gonext(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+}
+
+S32 LLScriptCompoundStatement::getSize()
+{
+ return 0;
+}
+
+void LLScriptCompoundStatement::recurse(FILE *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)
+{
+ if (gErrorToText.getErrors())
+ {
+ return;
+ }
+ switch(pass)
+ {
+ case LSCP_PRETTY_PRINT:
+ if (mStatement)
+ {
+ fdotabs(fp, tabs, tabsize);
+ fprintf(fp, "{\n");
+ mStatement->recurse(fp, tabs + 1, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fdotabs(fp, tabs, tabsize);
+ fprintf(fp, "}\n");
+ }
+ else
+ {
+ fdotabs(fp, tabs, tabsize);
+ fprintf(fp, "{\n");
+ fdotabs(fp, tabs, tabsize);
+ fprintf(fp, "}\n");
+ }
+ break;
+ case LSCP_EMIT_ASSEMBLY:
+ if (mStatement)
+ {
+ mStatement->recurse(fp, tabs + 1, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ }
+ break;
+ case LSCP_PRUNE:
+ if (mStatement)
+ {
+ mStatement->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ }
+ else
+ {
+ prunearg = FALSE;
+ }
+ break;
+ case LSCP_SCOPE_PASS1:
+ // compound statements create a new scope
+ if (mStatement)
+ {
+ mStatementScope = new LLScriptScope(gScopeStringTable);
+ mStatementScope->addParentScope(scope);
+ mStatement->recurse(fp, tabs, tabsize, pass, ptype, prunearg, mStatementScope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ }
+ break;
+ case LSCP_SCOPE_PASS2:
+ // compound statements create a new scope
+ if (mStatement)
+ {
+ mStatement->recurse(fp, tabs, tabsize, pass, ptype, prunearg, mStatementScope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ }
+ break;
+ default:
+ if (mStatement)
+ {
+ mStatement->recurse(fp, tabs + 1, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ }
+ break;
+ }
+ gonext(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+}
+
+void LLScriptEventHandler::addEvent(LLScriptEventHandler *event)
+{
+ if (mNextp)
+ {
+ event->mNextp = mNextp;
+ }
+ mNextp = event;
+}
+
+void LLScriptEventHandler::gonext(FILE *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)
+{
+ if (gErrorToText.getErrors())
+ {
+ return;
+ }
+ switch(pass)
+ {
+ case LSCP_PRETTY_PRINT:
+ if (mNextp)
+ {
+ mNextp->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ }
+ break;
+ default:
+ if (mNextp)
+ {
+ mNextp->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ }
+ break;
+ }
+}
+
+S32 LLScriptEventHandler::getSize()
+{
+ return mStackSpace;
+}
+
+U64 gCurrentHandler = 0;
+
+void print_cil_local_init(FILE* fp, LLScriptScopeEntry* scopeEntry)
+{
+ if(scopeEntry->mLocals.getNumber() > 0)
+ {
+ fprintf(fp, ".locals init (");
+ for(int local = 0; local < scopeEntry->mLocals.getNumber(); ++local)
+ {
+ if(local > 0)
+ {
+ fprintf(fp, ", ");
+ }
+ print_cil_type(fp, scopeEntry->mLocals.getType(local));
+ }
+ fprintf(fp, ")\n");
+ }
+}
+
+void LLScriptEventHandler::recurse(FILE *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)
+{
+ if (gErrorToText.getErrors())
+ {
+ return;
+ }
+ switch(pass)
+ {
+ case LSCP_PRETTY_PRINT:
+ mEventp->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ if (mStatement)
+ {
+ mStatement->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ }
+ else
+ {
+ fdotabs(fp, tabs, tabsize);
+ fprintf(fp, "{\n");
+ fdotabs(fp, tabs, tabsize);
+ fprintf(fp, "}\n");
+ }
+ break;
+ case LSCP_EMIT_ASSEMBLY:
+ mEventp->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ if (mStatement)
+ {
+ mStatement->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, getSize(), mScopeEntry, entrycount, NULL);
+ }
+ if (mbNeedTrailingReturn)
+ {
+ print_return(fp, mScopeEntry);
+ }
+ fprintf(fp, "\n");
+ break;
+ case LSCP_PRUNE:
+ mbNeedTrailingReturn = FALSE;
+ prunearg = TRUE;
+ mStatement->recurse(fp, tabs, tabsize, pass, LSPRUNE_EVENTS, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ if (!prunearg)
+ {
+ // this means that we didn't end with a return statement, need to add one
+ mbNeedTrailingReturn = TRUE;
+ }
+ break;
+ case LSCP_SCOPE_PASS1:
+ // create event level scope
+ mEventScope = new LLScriptScope(gScopeStringTable);
+ mEventScope->addParentScope(scope);
+
+ // add event parameters
+ mEventp->recurse(fp, tabs, tabsize, pass, ptype, prunearg, mEventScope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+
+ mStatement->recurse(fp, tabs, tabsize, pass, ptype, prunearg, mEventScope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ break;
+ case LSCP_SCOPE_PASS2:
+ mStatement->recurse(fp, tabs, tabsize, pass, ptype, prunearg, mEventScope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ break;
+ case LSCP_TYPE:
+ mScopeEntry = new LLScriptScopeEntry("Event", LIT_HANDLER, LST_NULL);
+ switch(mEventp->mType)
+ {
+ case LSTT_STATE_ENTRY:
+ break;
+ case LSTT_STATE_EXIT:
+ break;
+ case LSTT_TOUCH_START:
+ mScopeEntry->mFunctionArgs.addType(LST_INTEGER);
+ break;
+ case LSTT_TOUCH:
+ mScopeEntry->mFunctionArgs.addType(LST_INTEGER);
+ break;
+ case LSTT_TOUCH_END:
+ mScopeEntry->mFunctionArgs.addType(LST_INTEGER);
+ break;
+ case LSTT_COLLISION_START:
+ mScopeEntry->mFunctionArgs.addType(LST_INTEGER);
+ break;
+ case LSTT_COLLISION:
+ mScopeEntry->mFunctionArgs.addType(LST_INTEGER);
+ break;
+ case LSTT_COLLISION_END:
+ mScopeEntry->mFunctionArgs.addType(LST_INTEGER);
+ break;
+ case LSTT_LAND_COLLISION_START:
+ mScopeEntry->mFunctionArgs.addType(LST_VECTOR);
+ break;
+ case LSTT_LAND_COLLISION:
+ mScopeEntry->mFunctionArgs.addType(LST_VECTOR);
+ break;
+ case LSTT_LAND_COLLISION_END:
+ mScopeEntry->mFunctionArgs.addType(LST_VECTOR);
+ break;
+ case LSTT_INVENTORY:
+ mScopeEntry->mFunctionArgs.addType(LST_INTEGER);
+ break;
+ case LSTT_ATTACH:
+ mScopeEntry->mFunctionArgs.addType(LST_KEY);
+ break;
+ case LSTT_DATASERVER:
+ mScopeEntry->mFunctionArgs.addType(LST_KEY);
+ mScopeEntry->mFunctionArgs.addType(LST_STRING);
+ break;
+ case LSTT_TIMER:
+ break;
+ case LSTT_MOVING_START:
+ break;
+ case LSTT_MOVING_END:
+ break;
+ case LSTT_OBJECT_REZ:
+ mScopeEntry->mFunctionArgs.addType(LST_KEY);
+ break;
+ case LSTT_REMOTE_DATA:
+ mScopeEntry->mFunctionArgs.addType(LST_INTEGER);
+ mScopeEntry->mFunctionArgs.addType(LST_KEY);
+ mScopeEntry->mFunctionArgs.addType(LST_KEY);
+ mScopeEntry->mFunctionArgs.addType(LST_STRING);
+ mScopeEntry->mFunctionArgs.addType(LST_INTEGER);
+ mScopeEntry->mFunctionArgs.addType(LST_STRING);
+ break;
+ case LSTT_CHAT:
+ mScopeEntry->mFunctionArgs.addType(LST_INTEGER);
+ mScopeEntry->mFunctionArgs.addType(LST_STRING);
+ mScopeEntry->mFunctionArgs.addType(LST_KEY);
+ mScopeEntry->mFunctionArgs.addType(LST_STRING);
+ break;
+ case LSTT_SENSOR:
+ mScopeEntry->mFunctionArgs.addType(LST_INTEGER);
+ break;
+ case LSTT_CONTROL:
+ mScopeEntry->mFunctionArgs.addType(LST_KEY);
+ mScopeEntry->mFunctionArgs.addType(LST_INTEGER);
+ mScopeEntry->mFunctionArgs.addType(LST_INTEGER);
+ break;
+ case LSTT_LINK_MESSAGE:
+ mScopeEntry->mFunctionArgs.addType(LST_INTEGER);
+ mScopeEntry->mFunctionArgs.addType(LST_INTEGER);
+ mScopeEntry->mFunctionArgs.addType(LST_STRING);
+ mScopeEntry->mFunctionArgs.addType(LST_KEY);
+ break;
+ case LSTT_MONEY:
+ mScopeEntry->mFunctionArgs.addType(LST_KEY);
+ mScopeEntry->mFunctionArgs.addType(LST_INTEGER);
+ break;
+ case LSTT_EMAIL:
+ mScopeEntry->mFunctionArgs.addType(LST_STRING);
+ mScopeEntry->mFunctionArgs.addType(LST_STRING);
+ mScopeEntry->mFunctionArgs.addType(LST_STRING);
+ mScopeEntry->mFunctionArgs.addType(LST_STRING);
+ mScopeEntry->mFunctionArgs.addType(LST_INTEGER);
+ break;
+ case LSTT_REZ:
+ mScopeEntry->mFunctionArgs.addType(LST_INTEGER);
+ break;
+ case LSTT_NO_SENSOR:
+ break;
+ case LSTT_AT_TARGET:
+ mScopeEntry->mFunctionArgs.addType(LST_INTEGER);
+ mScopeEntry->mFunctionArgs.addType(LST_VECTOR);
+ mScopeEntry->mFunctionArgs.addType(LST_VECTOR);
+ break;
+ case LSTT_NOT_AT_TARGET:
+ break;
+ case LSTT_AT_ROT_TARGET:
+ mScopeEntry->mFunctionArgs.addType(LST_INTEGER);
+ mScopeEntry->mFunctionArgs.addType(LST_QUATERNION);
+ mScopeEntry->mFunctionArgs.addType(LST_QUATERNION);
+ break;
+ case LSTT_NOT_AT_ROT_TARGET:
+ break;
+ case LSTT_RTPERMISSIONS:
+ mScopeEntry->mFunctionArgs.addType(LST_INTEGER);
+ break;
+ case LSTT_HTTP_RESPONSE:
+ mScopeEntry->mFunctionArgs.addType(LST_KEY);
+ mScopeEntry->mFunctionArgs.addType(LST_INTEGER);
+ mScopeEntry->mFunctionArgs.addType(LST_LIST);
+ mScopeEntry->mFunctionArgs.addType(LST_STRING);
+ break;
+
+ default:
+ break;
+ }
+ mStatement->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ break;
+ case LSCP_RESOURCE:
+ // first determine resource counts for globals
+ count = 0;
+ mEventp->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ if (mStatement)
+ {
+ entrycount = 0;
+ mStatement->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, mScopeEntry, entrycount, NULL);
+ fprintf(fp, "Function Args: %s\n", mScopeEntry->mFunctionArgs.mString);
+ fprintf(fp, "Local List: %s\n", mScopeEntry->mLocals.mString);
+ }
+ mStackSpace = (S32)count;
+ break;
+ case LSCP_DETERMINE_HANDLERS:
+ count |= LSCRIPTStateBitField[mEventp->mType];
+ break;
+ case LSCP_EMIT_BYTE_CODE:
+ {
+ // order for event handler
+ // set jump table value
+ S32 jumpoffset;
+ jumpoffset = LSCRIPTDataSize[LST_INTEGER]*get_event_handler_jump_position(gCurrentHandler, mEventp->mType)*2;
+
+ integer2bytestream(chunk->mCodeChunk, jumpoffset, chunk->mCurrentOffset);
+
+ // 0 - 3: offset to actual data
+ S32 offsetoffset = chunk->mCurrentOffset;
+ S32 offsetdelta = 0;
+ chunk->addBytes(4);
+
+ // null terminated event name and null terminated parameters
+ if (mEventp)
+ {
+ LLScriptByteCodeChunk *event = new LLScriptByteCodeChunk(FALSE);
+ mEventp->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, event, heap, stacksize, entry, entrycount, NULL);
+ chunk->addBytes(event->mCodeChunk, event->mCurrentOffset);
+ delete event;
+ }
+ chunk->addBytes(1);
+
+ // now we're at the first opcode
+ offsetdelta = chunk->mCurrentOffset - offsetoffset;
+ integer2bytestream(chunk->mCodeChunk, offsetoffset, offsetdelta);
+
+ // get ready to compute the number of bytes of opcode
+ offsetdelta = chunk->mCurrentOffset;
+
+ if (mStatement)
+ {
+ LLScriptByteCodeChunk *statements = new LLScriptByteCodeChunk(TRUE);
+ mStatement->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, statements, heap, getSize(), mScopeEntry, entrycount, NULL);
+ statements->connectJumps();
+ chunk->addBytes(statements->mCodeChunk, statements->mCurrentOffset);
+ delete statements;
+ }
+ if (mbNeedTrailingReturn)
+ {
+ add_return(chunk, mScopeEntry);
+ }
+ // now stuff in the number of bytes of stack space that this routine needs
+ integer2bytestream(chunk->mCodeChunk, jumpoffset, getSize());
+ }
+ break;
+ case LSCP_EMIT_CIL_ASSEMBLY:
+
+ // Method signature prefix.
+ fprintf(fp, ".method public hidebysig instance default void ");
+
+ // Mangle event handler name by prefixing it with state name. Allows state changing by finding handlers prefixed with new state name.
+ fprintf(fp, entry->mIdentifier);
+
+ // Handler name and arguments.
+ mEventp->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+
+ // Method signature postfix.
+ fprintf(fp, " cil managed\n");
+
+ // Function header.
+ fprintf(fp,"{\n");
+ fprintf(fp, ".maxstack 500\n"); // TODO: Calculated stack size...
+
+ // Allocate space for locals.
+ print_cil_local_init(fp, mScopeEntry);
+
+ if (mStatement)
+ {
+ // Pass scope so identifiers can determine parameter or local.
+ mStatement->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, mScopeEntry, entrycount, NULL);
+ }
+
+ // Function footer.
+ fprintf(fp, "\nret\n"); // TODO: Check whether return needed?
+ fprintf(fp, "}\n");
+
+ break;
+ default:
+ mEventp->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ if (mStatement)
+ {
+ mStatement->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ }
+ break;
+ }
+ gonext(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+}
+
+void LLScriptFunctionDec::addFunctionParameter(LLScriptFunctionDec *dec)
+{
+ if (mNextp)
+ {
+ dec->mNextp = mNextp;
+ }
+ mNextp = dec;
+}
+
+void LLScriptFunctionDec::gonext(FILE *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)
+{
+ if (gErrorToText.getErrors())
+ {
+ return;
+ }
+ switch(pass)
+ {
+ case LSCP_PRETTY_PRINT:
+ if (mNextp)
+ {
+ fprintf(fp, ", ");
+ mNextp->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ }
+ break;
+ case LSCP_EMIT_ASSEMBLY:
+ if (mNextp)
+ {
+ fprintf(fp, ", ");
+ mNextp->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ }
+ break;
+ default:
+ if (mNextp)
+ {
+ mNextp->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ }
+ break;
+ }
+
+}
+
+S32 LLScriptFunctionDec::getSize()
+{
+ return 0;
+}
+
+void LLScriptFunctionDec::recurse(FILE *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)
+{
+ if (gErrorToText.getErrors())
+ {
+ return;
+ }
+ switch(pass)
+ {
+ case LSCP_PRETTY_PRINT:
+ fdotabs(fp, tabs, tabsize);
+ mType->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, " ");
+ mIdentifier->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ break;
+ case LSCP_EMIT_ASSEMBLY:
+ mType->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, " ");
+ mIdentifier->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ break;
+ case LSCP_SCOPE_PASS1:
+ // add function names into global scope
+ if (scope->checkEntry(mIdentifier->mName))
+ {
+ gErrorToText.writeError(fp, this, LSERROR_DUPLICATE_NAME);
+ }
+ else
+ {
+ mIdentifier->mScopeEntry = scope->addEntry(mIdentifier->mName, LIT_VARIABLE, mType->mType);
+ }
+ break;
+ case LSCP_RESOURCE:
+ {
+ // we're just tryng to determine how much space the variable needs
+ mIdentifier->mScopeEntry->mOffset = (S32)count;
+ mIdentifier->mScopeEntry->mSize = mType->getSize();
+ count += mIdentifier->mScopeEntry->mSize;
+ }
+ break;
+ case LSCP_EMIT_BYTE_CODE:
+ {
+ // return type
+ char typereturn;
+ if (mType)
+ {
+ typereturn = LSCRIPTTypeByte[mType->mType];
+ }
+ else
+ {
+ typereturn = LSCRIPTTypeByte[LST_NULL];
+ }
+ chunk->addBytes(&typereturn, 1);
+ // name
+#ifdef LSL_INCLUDE_DEBUG_INFO
+ chunk->addBytes(mIdentifier->mName, strlen(mIdentifier->mName) + 1);
+#else
+ chunk->addBytes(1);
+#endif
+ }
+ break;
+ case LSCP_BUILD_FUNCTION_ARGS:
+ {
+ entry->mFunctionArgs.addType(mType->mType);
+ }
+ break;
+ case LSCP_EMIT_CIL_ASSEMBLY:
+ mType->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, " ");
+ mIdentifier->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ break;
+ default:
+ mType->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mIdentifier->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ break;
+ }
+ gonext(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+}
+
+void LLScriptGlobalFunctions::addGlobalFunction(LLScriptGlobalFunctions *global)
+{
+ if (mNextp)
+ {
+ global->mNextp = mNextp;
+ }
+ mNextp = global;
+}
+
+void LLScriptGlobalFunctions::gonext(FILE *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)
+{
+ if (gErrorToText.getErrors())
+ {
+ return;
+ }
+ switch(pass)
+ {
+ case LSCP_PRETTY_PRINT:
+ if (mNextp)
+ {
+ mNextp->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ }
+ break;
+ default:
+ if (mNextp)
+ {
+ mNextp->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ }
+ break;
+ }
+}
+
+S32 LLScriptGlobalFunctions::getSize()
+{
+ return 0;
+}
+
+void LLScriptGlobalFunctions::recurse(FILE *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)
+{
+ if (gErrorToText.getErrors())
+ {
+ return;
+ }
+ switch(pass)
+ {
+ case LSCP_PRETTY_PRINT:
+ fdotabs(fp, tabs, tabsize);
+ if (mType)
+ {
+ mType->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, "\t");
+ }
+ mIdentifier->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ if (mParameters)
+ {
+ fprintf(fp, "( ");
+ mParameters->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, " )\n");
+ }
+ else
+ {
+ fprintf(fp, "()\n");
+ }
+ if (mStatements)
+ {
+ fdotabs(fp, tabs, tabsize);
+ mStatements->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, mIdentifier->mScopeEntry, entrycount, NULL);
+ }
+ else
+ {
+ fdotabs(fp, tabs, tabsize);
+ fprintf(fp, "{\n");
+ fdotabs(fp, tabs, tabsize);
+ fprintf(fp, "}\n");
+ }
+ break;
+ case LSCP_EMIT_ASSEMBLY:
+ mIdentifier->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ if (mParameters)
+ {
+ fprintf(fp, "( ");
+ mParameters->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, " )\n");
+ }
+ else
+ {
+ fprintf(fp, "()\n");
+ }
+ if (mStatements)
+ {
+ mStatements->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, mIdentifier->mScopeEntry->mSize, mIdentifier->mScopeEntry, entrycount, NULL);
+ }
+ if (mbNeedTrailingReturn)
+ {
+ print_return(fp, mIdentifier->mScopeEntry);
+ }
+ fprintf(fp, "\n");
+ break;
+ case LSCP_PRUNE:
+ mbNeedTrailingReturn = FALSE;
+ if (mType)
+ {
+ prunearg = TRUE;
+ mStatements->recurse(fp, tabs, tabsize, pass, LSPRUNE_GLOBAL_NON_VOIDS, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ if (!prunearg)
+ {
+ gErrorToText.writeError(fp, this, LSERROR_NO_RETURN);
+ }
+ }
+ else
+ {
+ prunearg = TRUE;
+ mStatements->recurse(fp, tabs, tabsize, pass, LSPRUNE_GLOBAL_VOIDS, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ if (!prunearg)
+ {
+ // this means that we didn't end with a return statement, need to add one
+ mbNeedTrailingReturn = TRUE;
+ }
+ }
+ break;
+ case LSCP_SCOPE_PASS1:
+ // add function names into global scope
+ if (scope->checkEntry(mIdentifier->mName))
+ {
+ gErrorToText.writeError(fp, this, LSERROR_DUPLICATE_NAME);
+ }
+ else
+ {
+ if (mType)
+ {
+ mIdentifier->mScopeEntry = scope->addEntry(mIdentifier->mName, LIT_FUNCTION, mType->mType);
+ }
+ else
+ {
+ mIdentifier->mScopeEntry = scope->addEntry(mIdentifier->mName, LIT_FUNCTION, LST_NULL);
+ }
+ }
+
+ // create function level scope
+ mFunctionScope = new LLScriptScope(gScopeStringTable);
+ mFunctionScope->addParentScope(scope);
+
+ // function parameters
+ if (mParameters)
+ {
+ mParameters->recurse(fp, tabs, tabsize, pass, ptype, prunearg, mFunctionScope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ }
+
+ mStatements->recurse(fp, tabs, tabsize, pass, ptype, prunearg, mFunctionScope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ break;
+ case LSCP_SCOPE_PASS2:
+ mStatements->recurse(fp, tabs, tabsize, pass, ptype, prunearg, mFunctionScope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+
+ if (mParameters)
+ {
+ if (mIdentifier->mScopeEntry)
+ {
+ mParameters->recurse(fp, tabs, tabsize, LSCP_BUILD_FUNCTION_ARGS, ptype, prunearg, mFunctionScope, type, basetype, count, chunk, heap, stacksize, mIdentifier->mScopeEntry, 0, NULL);
+ }
+ }
+ break;
+ case LSCP_TYPE:
+ if (mType)
+ {
+ mStatements->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, mType->mType, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ }
+ else
+ {
+ type = LST_NULL;
+ mStatements->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ }
+ break;
+ case LSCP_RESOURCE:
+ // first determine resource counts for globals
+ count = 0;
+
+ if (mParameters)
+ {
+ mParameters->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ }
+
+ if (mIdentifier->mScopeEntry)
+ {
+ // this isn't a bug . . . Offset is used to determine how much is params vs locals
+ mIdentifier->mScopeEntry->mOffset = (S32)count;
+ }
+
+ if (mStatements)
+ {
+ entrycount = 0;
+ mStatements->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, mIdentifier->mScopeEntry, entrycount, NULL);
+ fprintf(fp, "Function Args: %s\n", mIdentifier->mScopeEntry->mFunctionArgs.mString);
+ fprintf(fp, "Local List: %s\n", mIdentifier->mScopeEntry->mLocals.mString);
+ if (mIdentifier->mScopeEntry)
+ {
+ mIdentifier->mScopeEntry->mSize = (S32)count;
+ }
+ }
+ break;
+ case LSCP_EMIT_BYTE_CODE:
+ {
+ // order for global functions
+ // set jump table value
+ S32 jumpoffset = LSCRIPTDataSize[LST_INTEGER]*mIdentifier->mScopeEntry->mCount + LSCRIPTDataSize[LST_INTEGER];
+ integer2bytestream(chunk->mCodeChunk, jumpoffset, chunk->mCurrentOffset);
+
+ // 0 - 3: offset to actual data
+ S32 offsetoffset = chunk->mCurrentOffset;
+ S32 offsetdelta = 0;
+ chunk->addBytes(4);
+
+ // null terminated function name
+#ifdef LSL_INCLUDE_DEBUG_INFO
+ chunk->addBytes(mIdentifier->mName, strlen(mIdentifier->mName) + 1);
+#else
+ chunk->addBytes(1);
+#endif
+ // return type
+ char typereturn;
+ if (mType)
+ {
+ typereturn = LSCRIPTTypeByte[mType->mType];
+ }
+ else
+ {
+ typereturn = LSCRIPTTypeByte[LST_NULL];
+ }
+ chunk->addBytes(&typereturn, 1);
+
+ // null terminated parameters, followed by type
+ if (mParameters)
+ {
+ LLScriptByteCodeChunk *params = new LLScriptByteCodeChunk(FALSE);
+ mParameters->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, params, heap, stacksize, entry, entrycount, NULL);
+ chunk->addBytes(params->mCodeChunk, params->mCurrentOffset);
+ delete params;
+ }
+ chunk->addBytes(1);
+
+ // now we're at the first opcode
+ offsetdelta = chunk->mCurrentOffset - offsetoffset;
+ integer2bytestream(chunk->mCodeChunk, offsetoffset, offsetdelta);
+
+ if (mStatements)
+ {
+ LLScriptByteCodeChunk *statements = new LLScriptByteCodeChunk(TRUE);
+ mStatements->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, statements, heap, mIdentifier->mScopeEntry->mSize, mIdentifier->mScopeEntry, entrycount, NULL);
+ statements->connectJumps();
+ chunk->addBytes(statements->mCodeChunk, statements->mCurrentOffset);
+ delete statements;
+ }
+ if (mbNeedTrailingReturn)
+ {
+ add_return(chunk, mIdentifier->mScopeEntry);
+ }
+ }
+ break;
+ case LSCP_EMIT_CIL_ASSEMBLY:
+ {
+ // Function header.
+ fprintf(fp, ".method public hidebysig instance default ");
+ print_cil_type(fp, mType ? mType->mType : LST_NULL);
+ fprintf(fp, " ");
+ mIdentifier->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ if (mParameters)
+ {
+ fprintf(fp, "( ");
+ mParameters->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, " )");
+ }
+ else
+ {
+ fprintf(fp, "()");
+ }
+ fprintf(fp, " cil managed\n{\n");
+ fprintf(fp, ".maxstack 500\n"); // TODO: Calculated stack size...
+
+ // Allocate space for locals.
+ print_cil_local_init(fp, mIdentifier->mScopeEntry);
+
+ if (mStatements)
+ {
+ mStatements->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, mIdentifier->mScopeEntry->mSize, mIdentifier->mScopeEntry, entrycount, NULL);
+ }
+
+ // Function footer.
+ if (mbNeedTrailingReturn)
+ {
+ fprintf(fp, "ret\n");
+ }
+ fprintf(fp, "}\n");
+ fprintf(fp, "\n");
+ }
+ break;
+ default:
+ if (mType)
+ {
+ mType->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ }
+ mIdentifier->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ if (mParameters)
+ {
+ mParameters->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ }
+ if (mStatements)
+ {
+ mStatements->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ }
+ break;
+ }
+ gonext(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+}
+
+void LLScriptState::addState(LLScriptState *state)
+{
+ if (mNextp)
+ {
+ state->mNextp = mNextp;
+ }
+ mNextp = state;
+}
+
+void LLScriptState::gonext(FILE *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)
+{
+ if (gErrorToText.getErrors())
+ {
+ return;
+ }
+ switch(pass)
+ {
+ case LSCP_PRETTY_PRINT:
+ if (mNextp)
+ {
+ mNextp->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ }
+ break;
+ default:
+ if (mNextp)
+ {
+ mNextp->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ }
+ break;
+ }
+}
+
+S32 LLScriptState::getSize()
+{
+ return 0;
+}
+
+void LLScriptState::recurse(FILE *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)
+{
+ if (gErrorToText.getErrors())
+ {
+ return;
+ }
+ switch(pass)
+ {
+ case LSCP_PRETTY_PRINT:
+ fdotabs(fp, tabs, tabsize);
+ if (mType == LSSTYPE_DEFAULT)
+ {
+ mIdentifier->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, "\n");
+ fdotabs(fp, tabs, tabsize);
+ fprintf(fp, "{\n");
+ }
+ else
+ {
+ fprintf(fp, "state ");
+ mIdentifier->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, "\n");
+ fdotabs(fp, tabs, tabsize);
+ fprintf(fp, "{\n");
+ }
+ if (mEvent)
+ {
+ mEvent->recurse(fp, tabs + 1, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ }
+ fdotabs(fp, tabs, tabsize);
+ fprintf(fp, "}\n");
+ break;
+ case LSCP_EMIT_ASSEMBLY:
+ mIdentifier->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, ":\n");
+ if (mEvent)
+ {
+ fprintf(fp, "EVENTS\n");
+ mEvent->recurse(fp, tabs + 1, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, "\n");
+ }
+ break;
+ case LSCP_SCOPE_PASS1:
+ // add state name
+ if (scope->checkEntry(mIdentifier->mName))
+ {
+ gErrorToText.writeError(fp, this, LSERROR_DUPLICATE_NAME);
+ }
+ else
+ {
+ mIdentifier->mScopeEntry = scope->addEntry(mIdentifier->mName, LIT_STATE, LST_NULL);
+ }
+ // now do the events
+ if (mEvent)
+ {
+ mEvent->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ }
+ break;
+ case LSCP_SCOPE_PASS2:
+ if (mEvent)
+ {
+ mEvent->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ }
+ break;
+ case LSCP_TYPE:
+ if (mEvent)
+ {
+ mEvent->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ }
+ break;
+ case LSCP_EMIT_BYTE_CODE:
+ {
+ // order for states
+ // set jump table value
+
+ S32 jumpoffset;
+ if (LSL2_CURRENT_MAJOR_VERSION == LSL2_MAJOR_VERSION_TWO)
+ {
+ jumpoffset = LSCRIPTDataSize[LST_INTEGER]*3*mIdentifier->mScopeEntry->mCount + LSCRIPTDataSize[LST_INTEGER];
+ }
+ else
+ {
+ jumpoffset = LSCRIPTDataSize[LST_INTEGER]*2*mIdentifier->mScopeEntry->mCount + LSCRIPTDataSize[LST_INTEGER];
+ }
+ integer2bytestream(chunk->mCodeChunk, jumpoffset, chunk->mCurrentOffset);
+
+ // need to figure out what handlers this state has registered
+ // we'll use to count to find it
+ count = 0;
+
+ if (mEvent)
+ {
+ mEvent->recurse(fp, tabs, tabsize, LSCP_DETERMINE_HANDLERS, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ gCurrentHandler = count;
+ }
+
+ // add description word into chunk
+ if (LSL2_CURRENT_MAJOR_VERSION == LSL2_MAJOR_VERSION_TWO)
+ {
+ u642bytestream(chunk->mCodeChunk, jumpoffset, gCurrentHandler);
+ }
+ else
+ {
+ integer2bytestream(chunk->mCodeChunk, jumpoffset, (S32)gCurrentHandler);
+ }
+
+
+ // 0 - 3: offset to event jump table
+ S32 offsetoffset = chunk->mCurrentOffset;
+ S32 offsetdelta = 0;
+ chunk->addBytes(4);
+
+ // null terminated state name
+#ifdef LSL_INCLUDE_DEBUG_INFO
+ chunk->addBytes(mIdentifier->mName, strlen(mIdentifier->mName) + 1);
+#else
+ chunk->addBytes(1);
+#endif
+ // now we're at the jump table
+ offsetdelta = chunk->mCurrentOffset - offsetoffset;
+ integer2bytestream(chunk->mCodeChunk, offsetoffset, offsetdelta);
+
+ // add the events themselves
+ if (mEvent)
+ {
+ LLScriptByteCodeChunk *events = new LLScriptByteCodeChunk(FALSE);
+ // make space for event jump table
+ events->addBytes(LSCRIPTDataSize[LST_INTEGER]*get_number_of_event_handlers(gCurrentHandler)*2);
+ mEvent->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, events, heap, stacksize, entry, entrycount, NULL);
+ chunk->addBytes(events->mCodeChunk, events->mCurrentOffset);
+ delete events;
+ }
+ }
+ break;
+ case LSCP_EMIT_CIL_ASSEMBLY:
+ if (mEvent)
+ {
+ // Entry not used at this level, so pass state scope as entry parameter, to allow event handlers to do name mangling.
+ mEvent->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, mIdentifier->mScopeEntry, entrycount, NULL);
+ }
+ break;
+ default:
+ if (mType == LSSTYPE_DEFAULT)
+ {
+ }
+ else
+ {
+ mIdentifier->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ }
+ if (mEvent)
+ {
+ mEvent->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ }
+ break;
+ }
+ gonext(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+}
+
+S32 LLScriptScript::getSize()
+{
+ return 0;
+}
+
+LLScriptScript::LLScriptScript(LLScritpGlobalStorage *globals,
+ LLScriptState *states) :
+ LLScriptFilePosition(0, 0),
+ mStates(states), mGlobalScope(NULL), mGlobals(NULL), mGlobalFunctions(NULL), mGodLike(FALSE)
+{
+ const char DEFAULT_BYTECODE_FILENAME[] = "lscript.lso";
+ strcpy(mBytecodeDest, DEFAULT_BYTECODE_FILENAME);
+
+ LLScriptGlobalVariable *tvar;
+ LLScriptGlobalFunctions *tfunc;
+ LLScritpGlobalStorage *temp;
+
+ temp = globals;
+ while(temp)
+ {
+ if (temp->mbGlobalFunction)
+ {
+ if (!mGlobalFunctions)
+ {
+ mGlobalFunctions = (LLScriptGlobalFunctions *)temp->mGlobal;
+ }
+ else
+ {
+ tfunc = mGlobalFunctions;
+ while(tfunc->mNextp)
+ {
+ tfunc = tfunc->mNextp;
+ }
+ tfunc->mNextp = (LLScriptGlobalFunctions *)temp->mGlobal;
+ }
+ }
+ else
+ {
+ if (!mGlobals)
+ {
+ mGlobals = (LLScriptGlobalVariable *)temp->mGlobal;
+ }
+ else
+ {
+ tvar = mGlobals;
+ while(tvar->mNextp)
+ {
+ tvar = tvar->mNextp;
+ }
+ tvar->mNextp = (LLScriptGlobalVariable *)temp->mGlobal;
+ }
+ }
+ temp = temp->mNextp;
+ }
+}
+
+void LLScriptScript::setBytecodeDest(const char* dst_filename)
+{
+ strncpy(mBytecodeDest, dst_filename, MAX_STRING);
+ mBytecodeDest[MAX_STRING-1] = '\0';
+}
+
+void print_cil_globals(FILE* fp, LLScriptGlobalVariable* global)
+{
+ fprintf(fp, ".field private ");
+ print_cil_type(fp, global->mType->mType);
+ fprintf(fp, " ");
+ fprintf(fp, global->mIdentifier->mName);
+ fprintf(fp, "\n");
+ if(NULL != global->mNextp)
+ {
+ print_cil_globals(fp, global->mNextp);
+ }
+}
+
+void LLScriptScript::recurse(FILE *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)
+{
+ if (gErrorToText.getErrors())
+ {
+ return;
+ }
+ switch(pass)
+ {
+ case LSCP_PRETTY_PRINT:
+ if (mGlobals)
+ {
+ fdotabs(fp, tabs, tabsize);
+ mGlobals->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ }
+
+ if (mGlobalFunctions)
+ {
+ fdotabs(fp, tabs, tabsize);
+ mGlobalFunctions->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ }
+
+ fdotabs(fp, tabs, tabsize);
+ mStates->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ break;
+ case LSCP_PRUNE:
+ if (mGlobalFunctions)
+ {
+ mGlobalFunctions->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ }
+ mStates->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ break;
+ case LSCP_SCOPE_PASS1:
+ {
+ mGlobalScope = new LLScriptScope(gScopeStringTable);
+ // zeroth, add library functions to global scope
+ S32 i;
+ char *arg;
+ LLScriptScopeEntry *sentry;
+ for (i = 0; i < gScriptLibrary.mNextNumber; i++)
+ {
+ // First, check to make sure this isn't a god only function, or that the viewer's agent is a god.
+ if (!gScriptLibrary.mFunctions[i]->mGodOnly || mGodLike)
+ {
+ if (gScriptLibrary.mFunctions[i]->mReturnType)
+ sentry = mGlobalScope->addEntry(gScriptLibrary.mFunctions[i]->mName, LIT_LIBRARY_FUNCTION, char2type(*gScriptLibrary.mFunctions[i]->mReturnType));
+ else
+ sentry = mGlobalScope->addEntry(gScriptLibrary.mFunctions[i]->mName, LIT_LIBRARY_FUNCTION, LST_NULL);
+ sentry->mLibraryNumber = i;
+ arg = gScriptLibrary.mFunctions[i]->mArgs;
+ if (arg)
+ {
+ while (*arg)
+ {
+ sentry->mFunctionArgs.addType(char2type(*arg));
+ sentry->mSize += LSCRIPTDataSize[char2type(*arg)];
+ sentry->mOffset += LSCRIPTDataSize[char2type(*arg)];
+ arg++;
+ }
+ }
+ }
+ }
+ // first go and collect all the global variables
+ if (mGlobals)
+ mGlobals->recurse(fp, tabs, tabsize, pass, ptype, prunearg, mGlobalScope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ // second, do the global functions
+ if (mGlobalFunctions)
+ mGlobalFunctions->recurse(fp, tabs, tabsize, pass, ptype, prunearg, mGlobalScope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ // now do states
+ mStates->recurse(fp, tabs, tabsize, pass, ptype, prunearg, mGlobalScope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ break;
+ }
+ case LSCP_SCOPE_PASS2:
+ // now we're checking jumps, function calls, and state transitions
+ if (mGlobalFunctions)
+ mGlobalFunctions->recurse(fp, tabs, tabsize, pass, ptype, prunearg, mGlobalScope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mStates->recurse(fp, tabs, tabsize, pass, ptype, prunearg, mGlobalScope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ break;
+ case LSCP_TYPE:
+ // first we need to check global variables
+ if (mGlobals)
+ mGlobals->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ // now do global functions and states
+ if (mGlobalFunctions)
+ mGlobalFunctions->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mStates->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ break;
+ case LSCP_RESOURCE:
+ // first determine resource counts for globals
+ count = 0;
+ if (mGlobals)
+ mGlobals->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ // now do locals
+ if (mGlobalFunctions)
+ mGlobalFunctions->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mStates->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ break;
+ case LSCP_EMIT_ASSEMBLY:
+
+ if (mGlobals)
+ {
+ fprintf(fp, "GLOBALS\n");
+ fdotabs(fp, tabs, tabsize);
+ mGlobals->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, "\n");
+ }
+
+ if (mGlobalFunctions)
+ {
+ fprintf(fp, "GLOBAL FUNCTIONS\n");
+ fdotabs(fp, tabs, tabsize);
+ mGlobalFunctions->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, "\n");
+ }
+
+ fprintf(fp, "STATES\n");
+ fdotabs(fp, tabs, tabsize);
+ mStates->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, "\n");
+ break;
+ case LSCP_EMIT_BYTE_CODE:
+ {
+ // first, create data structure to hold the whole shebang
+ LLScriptScriptCodeChunk *code = new LLScriptScriptCodeChunk(TOP_OF_MEMORY);
+
+ // ok, let's add the registers, all zeroes for now
+ S32 i;
+ S32 nooffset = 0;
+
+ for (i = LREG_IP; i < LREG_EOF; i++)
+ {
+ if (i < LREG_NCE)
+ code->mRegisters->addBytes(4);
+ else if (LSL2_CURRENT_MAJOR_VERSION == LSL2_MAJOR_VERSION_TWO)
+ code->mRegisters->addBytes(8);
+ }
+ // global variables
+ if (mGlobals)
+ mGlobals->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, code->mGlobalVariables, code->mHeap, stacksize, entry, entrycount, NULL);
+
+ // put the ending heap block onto the heap
+ U8 *temp;
+ S32 size = lsa_create_data_block(&temp, NULL, 0);
+ code->mHeap->addBytes(temp, size);
+ delete [] temp;
+
+ // global functions
+ // make space for global function jump table
+ if (mGlobalFunctions)
+ {
+ code->mGlobalFunctions->addBytes(LSCRIPTDataSize[LST_INTEGER]*mGlobalScope->mFunctionCount + LSCRIPTDataSize[LST_INTEGER]);
+ integer2bytestream(code->mGlobalFunctions->mCodeChunk, nooffset, mGlobalScope->mFunctionCount);
+ mGlobalFunctions->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, code->mGlobalFunctions, NULL, stacksize, entry, entrycount, NULL);
+ }
+
+
+ nooffset = 0;
+ // states
+ // make space for state jump/info table
+ if (LSL2_CURRENT_MAJOR_VERSION == LSL2_MAJOR_VERSION_TWO)
+ {
+ code->mStates->addBytes(LSCRIPTDataSize[LST_INTEGER]*3*mGlobalScope->mStateCount + LSCRIPTDataSize[LST_INTEGER]);
+ }
+ else
+ {
+ code->mStates->addBytes(LSCRIPTDataSize[LST_INTEGER]*2*mGlobalScope->mStateCount + LSCRIPTDataSize[LST_INTEGER]);
+ }
+ integer2bytestream(code->mStates->mCodeChunk, nooffset, mGlobalScope->mStateCount);
+ mStates->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, code->mStates, NULL, stacksize, entry, entrycount, NULL);
+
+ // now, put it all together and spit it out
+ // we need
+ FILE *bcfp = LLFile::fopen(mBytecodeDest, "wb");
+
+ code->build(fp, bcfp);
+ fclose(bcfp);
+ }
+ break;
+ case LSCP_EMIT_CIL_ASSEMBLY:
+
+ // Output dependencies.
+ fprintf(fp, ".assembly extern mscorlib {.ver 1:0:5000:0}\n");
+ fprintf(fp, ".assembly extern LScriptLibrary {.ver 0:0:0:0}\n");
+
+ // Output assembly name.
+ fprintf(fp, ".assembly 'lsl' {.ver 0:0:0:0}\n");
+
+ // Output class header.
+ fprintf(fp, ".class public auto ansi beforefieldinit LSL extends [mscorlib]System.Object\n");
+ fprintf(fp, "{\n");
+
+ // Output globals as members.
+ if(NULL != mGlobals)
+ {
+ print_cil_globals(fp, mGlobals);
+ }
+
+ // Output "runtime". Only needed to allow stand alone execution. Not needed when compiling to DLL and using embedded runtime.
+ fprintf(fp, ".method public static hidebysig default void Main () cil managed\n");
+ fprintf(fp, "{\n");
+ fprintf(fp, ".entrypoint\n");
+ fprintf(fp, ".maxstack 2\n");
+ fprintf(fp, ".locals init (class LSL V_0)\n");
+ fprintf(fp, "newobj instance void class LSL::.ctor()\n");
+ fprintf(fp, "stloc.0\n");
+ fprintf(fp, "ldloc.0\n");
+ fprintf(fp, "callvirt instance void class LSL::defaultstate_entry()\n");
+ fprintf(fp, "ret\n");
+ fprintf(fp, "}\n");
+
+ // Output ctor header.
+ fprintf(fp, ".method public hidebysig specialname rtspecialname instance default void .ctor () cil managed\n");
+ fprintf(fp, "{\n");
+ fprintf(fp, ".maxstack 500\n");
+
+ // Initialise globals as members in ctor.
+ if (mGlobals)
+ {
+ fdotabs(fp, tabs, tabsize);
+ mGlobals->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, "\n");
+ }
+
+ // Output ctor footer.
+ fprintf(fp, "ldarg.0\n");
+ fprintf(fp, "call instance void valuetype [mscorlib]System.Object::.ctor()\n");
+ fprintf(fp, "ret\n");
+ fprintf(fp, "}\n");
+
+ // Output functions as methods.
+ if (mGlobalFunctions)
+ {
+ fdotabs(fp, tabs, tabsize);
+ mGlobalFunctions->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, "\n");
+ }
+
+ // Output states as name mangled methods.
+ fdotabs(fp, tabs, tabsize);
+ mStates->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, "\n");
+
+ // Output class footer.
+ fprintf(fp, "}\n");
+
+ break;
+ default:
+ if (mGlobals)
+ mGlobals->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ if (mGlobalFunctions)
+ mGlobalFunctions->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mStates->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ break;
+ }
+}