initial port of the new interpreter

This commit is contained in:
Jeff Hutchinson 2021-03-30 19:33:19 -04:00
parent 5d2654b1ba
commit 35500a87c6
47 changed files with 3675 additions and 5839 deletions

View file

@ -331,7 +331,7 @@ DefineEngineStringlyVariadicMethod(GameConnection, setConnectArgs, void, 3, 17,
"@see GameConnection::onConnect()\n\n") "@see GameConnection::onConnect()\n\n")
{ {
StringStackWrapper args(argc - 2, argv + 2); ConsoleValueToStringArrayWrapper args(argc - 2, argv + 2);
object->setConnectArgs(args.count(), args); object->setConnectArgs(args.count(), args);
} }
@ -494,11 +494,17 @@ bool GameConnection::readConnectRequest(BitStream *stream, const char **errorStr
*errorString = "CR_INVALID_ARGS"; *errorString = "CR_INVALID_ARGS";
return false; return false;
} }
ConsoleValueRef connectArgv[MaxConnectArgs + 3]; ConsoleValue connectArgv[MaxConnectArgs + 3];
ConsoleValue connectArgvValue[MaxConnectArgs + 3]; ConsoleValue connectArgvValue[MaxConnectArgs + 3];
// TODO(JTH): Fix pls.
AssertISV(false, "TODO: FIX CONSOLE VALUE");
return false;
/*
for(U32 i = 0; i < mConnectArgc+3; i++) for(U32 i = 0; i < mConnectArgc+3; i++)
{ {
connectArgv[i].value = &connectArgvValue[i]; connectArgv[i].value = &connectArgvValue[i];
connectArgvValue[i].init(); connectArgvValue[i].init();
} }
@ -524,6 +530,7 @@ bool GameConnection::readConnectRequest(BitStream *stream, const char **errorStr
return false; return false;
} }
return true; return true;
*/
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
@ -1088,7 +1095,7 @@ bool GameConnection::readDemoStartBlock(BitStream *stream)
void GameConnection::demoPlaybackComplete() void GameConnection::demoPlaybackComplete()
{ {
static const char* demoPlaybackArgv[1] = { "demoPlaybackComplete" }; static const char* demoPlaybackArgv[1] = { "demoPlaybackComplete" };
static StringStackConsoleWrapper demoPlaybackCmd(1, demoPlaybackArgv); static StringArrayToConsoleValueWrapper demoPlaybackCmd(1, demoPlaybackArgv);
Sim::postCurrentEvent(Sim::getRootGroup(), new SimConsoleEvent(demoPlaybackCmd.argc, demoPlaybackCmd.argv, false)); Sim::postCurrentEvent(Sim::getRootGroup(), new SimConsoleEvent(demoPlaybackCmd.argc, demoPlaybackCmd.argv, false));
Parent::demoPlaybackComplete(); Parent::demoPlaybackComplete();

View file

@ -251,7 +251,7 @@ DefineEngineStringlyVariadicFunction( commandToServer, void, 2, RemoteCommandEve
NetConnection *conn = NetConnection::getConnectionToServer(); NetConnection *conn = NetConnection::getConnectionToServer();
if(!conn) if(!conn)
return; return;
StringStackWrapper args(argc - 1, argv + 1); ConsoleValueToStringArrayWrapper args(argc - 1, argv + 1);
RemoteCommandEvent::sendRemoteCommand(conn, args.count(), args); RemoteCommandEvent::sendRemoteCommand(conn, args.count(), args);
} }
@ -289,7 +289,7 @@ DefineEngineStringlyVariadicFunction( commandToClient, void, 3, RemoteCommandEve
NetConnection *conn; NetConnection *conn;
if(!Sim::findObject(argv[1], conn)) if(!Sim::findObject(argv[1], conn))
return; return;
StringStackWrapper args(argc - 2, argv + 2); ConsoleValueToStringArrayWrapper args(argc - 2, argv + 2);
RemoteCommandEvent::sendRemoteCommand(conn, args.count(), args); RemoteCommandEvent::sendRemoteCommand(conn, args.count(), args);
} }

View file

@ -236,13 +236,13 @@ TCPObject::~TCPObject()
} }
} }
bool TCPObject::processArguments(S32 argc, ConsoleValueRef *argv) bool TCPObject::processArguments(S32 argc, ConsoleValue *argv)
{ {
if(argc == 0) if(argc == 0)
return true; return true;
else if(argc == 1) else if(argc == 1)
{ {
addToTable(NetSocket::fromHandle(dAtoi(argv[0]))); addToTable(NetSocket::fromHandle(argv[0].getInt()));
return true; return true;
} }
return false; return false;

View file

@ -83,7 +83,7 @@ public:
void disconnect(); void disconnect();
State getState() { return mState; } State getState() { return mState; }
bool processArguments(S32 argc, ConsoleValueRef *argv); bool processArguments(S32 argc, ConsoleValue *argv);
void send(const U8 *buffer, U32 bufferLen); void send(const U8 *buffer, U32 bufferLen);
///Send an entire file over tcp ///Send an entire file over tcp

View file

@ -158,7 +158,7 @@ SimXMLDocument::~SimXMLDocument()
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// Included for completeness. // Included for completeness.
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
bool SimXMLDocument::processArguments(S32 argc, ConsoleValueRef *argv) bool SimXMLDocument::processArguments(S32 argc, ConsoleValue *argv)
{ {
return argc == 0; return argc == 0;
} }

View file

@ -57,7 +57,7 @@ class SimXMLDocument: public SimObject
// tie in to the script language. The .cc file has more in depth // tie in to the script language. The .cc file has more in depth
// comments on these. // comments on these.
//----------------------------------------------------------------------- //-----------------------------------------------------------------------
bool processArguments(S32 argc, ConsoleValueRef *argv); bool processArguments(S32 argc, ConsoleValue *argv);
bool onAdd(); bool onAdd();
void onRemove(); void onRemove();
static void initPersistFields(); static void initPersistFields();

View file

@ -39,8 +39,15 @@ enum TypeReq
TypeReqNone, TypeReqNone,
TypeReqUInt, TypeReqUInt,
TypeReqFloat, TypeReqFloat,
TypeReqString, TypeReqString
TypeReqVar };
enum ExprNodeName
{
NameExprNode,
NameFloatNode,
NameIntNode,
NameVarNode
}; };
/// Representation of a node for the scripting language parser. /// Representation of a node for the scripting language parser.
@ -52,7 +59,7 @@ enum TypeReq
/// each representing a different language construct. /// each representing a different language construct.
struct StmtNode struct StmtNode
{ {
StmtNode *mNext; ///< Next entry in parse tree. StmtNode* next; ///< Next entry in parse tree.
StmtNode(); StmtNode();
virtual ~StmtNode() {} virtual ~StmtNode() {}
@ -62,7 +69,7 @@ struct StmtNode
/// ///
void append(StmtNode* next); void append(StmtNode* next);
StmtNode *getNext() const { return mNext; } StmtNode* getNext() const { return next; }
/// @} /// @}
@ -92,7 +99,7 @@ struct StmtNode
/// Helper macro /// Helper macro
#ifndef DEBUG_AST_NODES #ifndef DEBUG_AST_NODES
# define DBG_STMT_TYPE(s) virtual String dbgStmtType() const { return String(#s); } # define DBG_STMT_TYPE(s) virtual const char* dbgStmtType() const { return "#s"; }
#else #else
# define DBG_STMT_TYPE(s) # define DBG_STMT_TYPE(s)
#endif #endif
@ -117,11 +124,13 @@ struct ContinueStmtNode : StmtNode
/// A mathematical expression. /// A mathematical expression.
struct ExprNode : StmtNode struct ExprNode : StmtNode
{ {
ExprNode* optimizedNode;
U32 compileStmt(CodeStream& codeStream, U32 ip); U32 compileStmt(CodeStream& codeStream, U32 ip);
virtual U32 compile(CodeStream& codeStream, U32 ip, TypeReq type) = 0; virtual U32 compile(CodeStream& codeStream, U32 ip, TypeReq type) = 0;
virtual TypeReq getPreferredType() = 0; virtual TypeReq getPreferredType() = 0;
virtual ExprNodeName getExprNodeNameEnum() const { return NameExprNode; }
}; };
struct ReturnStmtNode : StmtNode struct ReturnStmtNode : StmtNode
@ -205,6 +214,9 @@ struct FloatBinaryExprNode : BinaryExprNode
static FloatBinaryExprNode* alloc(S32 lineNumber, S32 op, ExprNode* left, ExprNode* right); static FloatBinaryExprNode* alloc(S32 lineNumber, S32 op, ExprNode* left, ExprNode* right);
U32 compile(CodeStream& codeStream, U32 ip, TypeReq type); U32 compile(CodeStream& codeStream, U32 ip, TypeReq type);
bool optimize();
TypeReq getPreferredType(); TypeReq getPreferredType();
DBG_STMT_TYPE(FloatBinaryExprNode); DBG_STMT_TYPE(FloatBinaryExprNode);
}; };
@ -231,6 +243,8 @@ struct IntBinaryExprNode : BinaryExprNode
void getSubTypeOperand(); void getSubTypeOperand();
bool optimize();
U32 compile(CodeStream& codeStream, U32 ip, TypeReq type); U32 compile(CodeStream& codeStream, U32 ip, TypeReq type);
TypeReq getPreferredType(); TypeReq getPreferredType();
DBG_STMT_TYPE(IntBinaryExprNode); DBG_STMT_TYPE(IntBinaryExprNode);
@ -300,6 +314,7 @@ struct VarNode : ExprNode
U32 compile(CodeStream& codeStream, U32 ip, TypeReq type); U32 compile(CodeStream& codeStream, U32 ip, TypeReq type);
TypeReq getPreferredType(); TypeReq getPreferredType();
virtual ExprNodeName getExprNodeNameEnum() const { return NameVarNode; }
DBG_STMT_TYPE(VarNode); DBG_STMT_TYPE(VarNode);
}; };
@ -312,6 +327,7 @@ struct IntNode : ExprNode
U32 compile(CodeStream& codeStream, U32 ip, TypeReq type); U32 compile(CodeStream& codeStream, U32 ip, TypeReq type);
TypeReq getPreferredType(); TypeReq getPreferredType();
virtual ExprNodeName getExprNodeNameEnum() const { return NameIntNode; }
DBG_STMT_TYPE(IntNode); DBG_STMT_TYPE(IntNode);
}; };
@ -324,6 +340,7 @@ struct FloatNode : ExprNode
U32 compile(CodeStream& codeStream, U32 ip, TypeReq type); U32 compile(CodeStream& codeStream, U32 ip, TypeReq type);
TypeReq getPreferredType(); TypeReq getPreferredType();
virtual ExprNodeName getExprNodeNameEnum() const { return NameFloatNode; }
DBG_STMT_TYPE(FloatNode); DBG_STMT_TYPE(FloatNode);
}; };
@ -435,6 +452,7 @@ struct FuncCallExprNode : ExprNode
U32 callType; U32 callType;
enum { enum {
FunctionCall, FunctionCall,
StaticCall,
MethodCall, MethodCall,
ParentCall ParentCall
}; };
@ -446,18 +464,6 @@ struct FuncCallExprNode : ExprNode
DBG_STMT_TYPE(FuncCallExprNode); DBG_STMT_TYPE(FuncCallExprNode);
}; };
struct FuncPointerCallExprNode : ExprNode
{
ExprNode *funcPointer;
ExprNode *args;
static FuncPointerCallExprNode *alloc(S32 lineNumber, ExprNode *stmt, ExprNode *args);
U32 compile(CodeStream &codeStream, U32 ip, TypeReq type);
TypeReq getPreferredType();
DBG_STMT_TYPE(FuncPointerCallExprNode);
};
struct AssertCallExprNode : ExprNode struct AssertCallExprNode : ExprNode
{ {
ExprNode* testExpr; ExprNode* testExpr;
@ -587,8 +593,6 @@ struct FunctionDeclStmtNode : StmtNode
}; };
extern StmtNode* gStatementList; extern StmtNode* gStatementList;
extern StmtNode *gAnonFunctionList;
extern U32 gAnonFunctionID;
extern ExprEvalState gEvalState; extern ExprEvalState gEvalState;
#endif #endif

View file

@ -1,5 +1,5 @@
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Copyright (c) 2012 GarageGames, LLC // Copyright (c) 2013 GarageGames, LLC
// //
// Permission is hereby granted, free of charge, to any person obtaining a copy // Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to // of this software and associated documentation files (the "Software"), to
@ -20,7 +20,6 @@
// IN THE SOFTWARE. // IN THE SOFTWARE.
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
#include "platform/platform.h"
#include "console/console.h" #include "console/console.h"
#include "console/compiler.h" #include "console/compiler.h"
#include "console/consoleInternal.h" #include "console/consoleInternal.h"
@ -116,6 +115,7 @@ FloatBinaryExprNode *FloatBinaryExprNode::alloc(S32 lineNumber, S32 op, ExprNode
FloatBinaryExprNode* ret = (FloatBinaryExprNode*)consoleAlloc(sizeof(FloatBinaryExprNode)); FloatBinaryExprNode* ret = (FloatBinaryExprNode*)consoleAlloc(sizeof(FloatBinaryExprNode));
constructInPlace(ret); constructInPlace(ret);
ret->dbgLineNumber = lineNumber; ret->dbgLineNumber = lineNumber;
ret->optimizedNode = NULL;
ret->op = op; ret->op = op;
ret->left = left; ret->left = left;
@ -129,6 +129,7 @@ IntBinaryExprNode *IntBinaryExprNode::alloc(S32 lineNumber, S32 op, ExprNode *le
IntBinaryExprNode* ret = (IntBinaryExprNode*)consoleAlloc(sizeof(IntBinaryExprNode)); IntBinaryExprNode* ret = (IntBinaryExprNode*)consoleAlloc(sizeof(IntBinaryExprNode));
constructInPlace(ret); constructInPlace(ret);
ret->dbgLineNumber = lineNumber; ret->dbgLineNumber = lineNumber;
ret->optimizedNode = NULL;
ret->op = op; ret->op = op;
ret->left = left; ret->left = left;
@ -142,6 +143,7 @@ StreqExprNode *StreqExprNode::alloc(S32 lineNumber, ExprNode *left, ExprNode *ri
StreqExprNode* ret = (StreqExprNode*)consoleAlloc(sizeof(StreqExprNode)); StreqExprNode* ret = (StreqExprNode*)consoleAlloc(sizeof(StreqExprNode));
constructInPlace(ret); constructInPlace(ret);
ret->dbgLineNumber = lineNumber; ret->dbgLineNumber = lineNumber;
ret->optimizedNode = NULL;
ret->left = left; ret->left = left;
ret->right = right; ret->right = right;
ret->eq = eq; ret->eq = eq;
@ -149,11 +151,12 @@ StreqExprNode *StreqExprNode::alloc(S32 lineNumber, ExprNode *left, ExprNode *ri
return ret; return ret;
} }
StrcatExprNode *StrcatExprNode::alloc(S32 lineNumber, ExprNode *left, ExprNode *right, S32 appendChar) StrcatExprNode* StrcatExprNode::alloc(S32 lineNumber, ExprNode* left, ExprNode* right, int appendChar)
{ {
StrcatExprNode* ret = (StrcatExprNode*)consoleAlloc(sizeof(StrcatExprNode)); StrcatExprNode* ret = (StrcatExprNode*)consoleAlloc(sizeof(StrcatExprNode));
constructInPlace(ret); constructInPlace(ret);
ret->dbgLineNumber = lineNumber; ret->dbgLineNumber = lineNumber;
ret->optimizedNode = NULL;
ret->left = left; ret->left = left;
ret->right = right; ret->right = right;
ret->appendChar = appendChar; ret->appendChar = appendChar;
@ -166,6 +169,7 @@ CommaCatExprNode *CommaCatExprNode::alloc(S32 lineNumber, ExprNode *left, ExprNo
CommaCatExprNode* ret = (CommaCatExprNode*)consoleAlloc(sizeof(CommaCatExprNode)); CommaCatExprNode* ret = (CommaCatExprNode*)consoleAlloc(sizeof(CommaCatExprNode));
constructInPlace(ret); constructInPlace(ret);
ret->dbgLineNumber = lineNumber; ret->dbgLineNumber = lineNumber;
ret->optimizedNode = NULL;
ret->left = left; ret->left = left;
ret->right = right; ret->right = right;
@ -177,6 +181,7 @@ IntUnaryExprNode *IntUnaryExprNode::alloc(S32 lineNumber, S32 op, ExprNode *expr
IntUnaryExprNode* ret = (IntUnaryExprNode*)consoleAlloc(sizeof(IntUnaryExprNode)); IntUnaryExprNode* ret = (IntUnaryExprNode*)consoleAlloc(sizeof(IntUnaryExprNode));
constructInPlace(ret); constructInPlace(ret);
ret->dbgLineNumber = lineNumber; ret->dbgLineNumber = lineNumber;
ret->optimizedNode = NULL;
ret->op = op; ret->op = op;
ret->expr = expr; ret->expr = expr;
return ret; return ret;
@ -187,6 +192,7 @@ FloatUnaryExprNode *FloatUnaryExprNode::alloc(S32 lineNumber, S32 op, ExprNode *
FloatUnaryExprNode* ret = (FloatUnaryExprNode*)consoleAlloc(sizeof(FloatUnaryExprNode)); FloatUnaryExprNode* ret = (FloatUnaryExprNode*)consoleAlloc(sizeof(FloatUnaryExprNode));
constructInPlace(ret); constructInPlace(ret);
ret->dbgLineNumber = lineNumber; ret->dbgLineNumber = lineNumber;
ret->optimizedNode = NULL;
ret->op = op; ret->op = op;
ret->expr = expr; ret->expr = expr;
return ret; return ret;
@ -197,6 +203,7 @@ VarNode *VarNode::alloc(S32 lineNumber, StringTableEntry varName, ExprNode *arra
VarNode* ret = (VarNode*)consoleAlloc(sizeof(VarNode)); VarNode* ret = (VarNode*)consoleAlloc(sizeof(VarNode));
constructInPlace(ret); constructInPlace(ret);
ret->dbgLineNumber = lineNumber; ret->dbgLineNumber = lineNumber;
ret->optimizedNode = NULL;
ret->varName = varName; ret->varName = varName;
ret->arrayIndex = arrayIndex; ret->arrayIndex = arrayIndex;
return ret; return ret;
@ -207,6 +214,7 @@ IntNode *IntNode::alloc(S32 lineNumber, S32 value)
IntNode* ret = (IntNode*)consoleAlloc(sizeof(IntNode)); IntNode* ret = (IntNode*)consoleAlloc(sizeof(IntNode));
constructInPlace(ret); constructInPlace(ret);
ret->dbgLineNumber = lineNumber; ret->dbgLineNumber = lineNumber;
ret->optimizedNode = NULL;
ret->value = value; ret->value = value;
return ret; return ret;
} }
@ -216,6 +224,7 @@ ConditionalExprNode *ConditionalExprNode::alloc(S32 lineNumber, ExprNode *testEx
ConditionalExprNode* ret = (ConditionalExprNode*)consoleAlloc(sizeof(ConditionalExprNode)); ConditionalExprNode* ret = (ConditionalExprNode*)consoleAlloc(sizeof(ConditionalExprNode));
constructInPlace(ret); constructInPlace(ret);
ret->dbgLineNumber = lineNumber; ret->dbgLineNumber = lineNumber;
ret->optimizedNode = NULL;
ret->testExpr = testExpr; ret->testExpr = testExpr;
ret->trueExpr = trueExpr; ret->trueExpr = trueExpr;
ret->falseExpr = falseExpr; ret->falseExpr = falseExpr;
@ -229,6 +238,7 @@ FloatNode *FloatNode::alloc(S32 lineNumber, F64 value)
constructInPlace(ret); constructInPlace(ret);
ret->dbgLineNumber = lineNumber; ret->dbgLineNumber = lineNumber;
ret->optimizedNode = NULL;
ret->value = value; ret->value = value;
return ret; return ret;
} }
@ -237,12 +247,15 @@ StrConstNode *StrConstNode::alloc(S32 lineNumber, char *str, bool tag, bool doc)
{ {
StrConstNode* ret = (StrConstNode*)consoleAlloc(sizeof(StrConstNode)); StrConstNode* ret = (StrConstNode*)consoleAlloc(sizeof(StrConstNode));
constructInPlace(ret); constructInPlace(ret);
S32 len = dStrlen(str);
ret->dbgLineNumber = lineNumber; ret->dbgLineNumber = lineNumber;
dsize_t retStrLen = dStrlen(str) + 1; ret->optimizedNode = NULL;
ret->str = (char *)consoleAlloc(retStrLen); ret->str = (char*)consoleAlloc(len + 1);
ret->tag = tag; ret->tag = tag;
ret->doc = doc; ret->doc = doc;
dStrcpy(ret->str, str, retStrLen); dStrcpy(ret->str, str, len);
ret->str[len] = '\0';
return ret; return ret;
} }
@ -252,6 +265,7 @@ ConstantNode *ConstantNode::alloc(S32 lineNumber, StringTableEntry value)
ConstantNode* ret = (ConstantNode*)consoleAlloc(sizeof(ConstantNode)); ConstantNode* ret = (ConstantNode*)consoleAlloc(sizeof(ConstantNode));
constructInPlace(ret); constructInPlace(ret);
ret->dbgLineNumber = lineNumber; ret->dbgLineNumber = lineNumber;
ret->optimizedNode = NULL;
ret->value = value; ret->value = value;
return ret; return ret;
} }
@ -261,6 +275,7 @@ AssignExprNode *AssignExprNode::alloc(S32 lineNumber, StringTableEntry varName,
AssignExprNode* ret = (AssignExprNode*)consoleAlloc(sizeof(AssignExprNode)); AssignExprNode* ret = (AssignExprNode*)consoleAlloc(sizeof(AssignExprNode));
constructInPlace(ret); constructInPlace(ret);
ret->dbgLineNumber = lineNumber; ret->dbgLineNumber = lineNumber;
ret->optimizedNode = NULL;
ret->varName = varName; ret->varName = varName;
ret->expr = expr; ret->expr = expr;
ret->arrayIndex = arrayIndex; ret->arrayIndex = arrayIndex;
@ -273,6 +288,7 @@ AssignOpExprNode *AssignOpExprNode::alloc(S32 lineNumber, StringTableEntry varNa
AssignOpExprNode* ret = (AssignOpExprNode*)consoleAlloc(sizeof(AssignOpExprNode)); AssignOpExprNode* ret = (AssignOpExprNode*)consoleAlloc(sizeof(AssignOpExprNode));
constructInPlace(ret); constructInPlace(ret);
ret->dbgLineNumber = lineNumber; ret->dbgLineNumber = lineNumber;
ret->optimizedNode = NULL;
ret->varName = varName; ret->varName = varName;
ret->expr = expr; ret->expr = expr;
ret->arrayIndex = arrayIndex; ret->arrayIndex = arrayIndex;
@ -296,6 +312,7 @@ TTagDerefNode *TTagDerefNode::alloc(S32 lineNumber, ExprNode *expr)
TTagDerefNode* ret = (TTagDerefNode*)consoleAlloc(sizeof(TTagDerefNode)); TTagDerefNode* ret = (TTagDerefNode*)consoleAlloc(sizeof(TTagDerefNode));
constructInPlace(ret); constructInPlace(ret);
ret->dbgLineNumber = lineNumber; ret->dbgLineNumber = lineNumber;
ret->optimizedNode = NULL;
ret->expr = expr; ret->expr = expr;
return ret; return ret;
} }
@ -305,6 +322,7 @@ TTagExprNode *TTagExprNode::alloc(S32 lineNumber, StringTableEntry tag)
TTagExprNode* ret = (TTagExprNode*)consoleAlloc(sizeof(TTagExprNode)); TTagExprNode* ret = (TTagExprNode*)consoleAlloc(sizeof(TTagExprNode));
constructInPlace(ret); constructInPlace(ret);
ret->dbgLineNumber = lineNumber; ret->dbgLineNumber = lineNumber;
ret->optimizedNode = NULL;
ret->tag = tag; ret->tag = tag;
return ret; return ret;
} }
@ -314,28 +332,21 @@ FuncCallExprNode *FuncCallExprNode::alloc(S32 lineNumber, StringTableEntry funcN
FuncCallExprNode* ret = (FuncCallExprNode*)consoleAlloc(sizeof(FuncCallExprNode)); FuncCallExprNode* ret = (FuncCallExprNode*)consoleAlloc(sizeof(FuncCallExprNode));
constructInPlace(ret); constructInPlace(ret);
ret->dbgLineNumber = lineNumber; ret->dbgLineNumber = lineNumber;
ret->optimizedNode = NULL;
ret->funcName = funcName; ret->funcName = funcName;
ret->nameSpace = nameSpace; ret->nameSpace = nameSpace;
ret->args = args; ret->args = args;
if (dot) if (dot)
ret->callType = MethodCall; ret->callType = MethodCall;
else else if (nameSpace != NULL)
{ {
if (nameSpace && !dStricmp(nameSpace, "Parent")) if (dStricmp(nameSpace, "Parent") == 0)
ret->callType = ParentCall; ret->callType = ParentCall;
else
ret->callType = StaticCall;
}
else else
ret->callType = FunctionCall; ret->callType = FunctionCall;
}
return ret;
}
FuncPointerCallExprNode *FuncPointerCallExprNode::alloc(S32 lineNumber, ExprNode *funcPointer, ExprNode *args)
{
FuncPointerCallExprNode *ret = (FuncPointerCallExprNode *)consoleAlloc(sizeof(FuncPointerCallExprNode));
constructInPlace(ret);
ret->dbgLineNumber = lineNumber;
ret->funcPointer = funcPointer;
ret->args = args;
return ret; return ret;
} }
@ -361,6 +372,7 @@ SlotAccessNode *SlotAccessNode::alloc(S32 lineNumber, ExprNode *objectExpr, Expr
{ {
SlotAccessNode* ret = (SlotAccessNode*)consoleAlloc(sizeof(SlotAccessNode)); SlotAccessNode* ret = (SlotAccessNode*)consoleAlloc(sizeof(SlotAccessNode));
constructInPlace(ret); constructInPlace(ret);
ret->optimizedNode = NULL;
ret->dbgLineNumber = lineNumber; ret->dbgLineNumber = lineNumber;
ret->objectExpr = objectExpr; ret->objectExpr = objectExpr;
ret->arrayExpr = arrayExpr; ret->arrayExpr = arrayExpr;
@ -373,6 +385,7 @@ InternalSlotAccessNode *InternalSlotAccessNode::alloc(S32 lineNumber, ExprNode *
InternalSlotAccessNode* ret = (InternalSlotAccessNode*)consoleAlloc(sizeof(InternalSlotAccessNode)); InternalSlotAccessNode* ret = (InternalSlotAccessNode*)consoleAlloc(sizeof(InternalSlotAccessNode));
constructInPlace(ret); constructInPlace(ret);
ret->dbgLineNumber = lineNumber; ret->dbgLineNumber = lineNumber;
ret->optimizedNode = NULL;
ret->objectExpr = objectExpr; ret->objectExpr = objectExpr;
ret->slotExpr = slotExpr; ret->slotExpr = slotExpr;
ret->recurse = recurse; ret->recurse = recurse;
@ -384,6 +397,7 @@ SlotAssignNode *SlotAssignNode::alloc(S32 lineNumber, ExprNode *objectExpr, Expr
SlotAssignNode* ret = (SlotAssignNode*)consoleAlloc(sizeof(SlotAssignNode)); SlotAssignNode* ret = (SlotAssignNode*)consoleAlloc(sizeof(SlotAssignNode));
constructInPlace(ret); constructInPlace(ret);
ret->dbgLineNumber = lineNumber; ret->dbgLineNumber = lineNumber;
ret->optimizedNode = NULL;
ret->objectExpr = objectExpr; ret->objectExpr = objectExpr;
ret->arrayExpr = arrayExpr; ret->arrayExpr = arrayExpr;
ret->slotName = slotName; ret->slotName = slotName;
@ -397,6 +411,7 @@ SlotAssignOpNode *SlotAssignOpNode::alloc(S32 lineNumber, ExprNode *objectExpr,
SlotAssignOpNode* ret = (SlotAssignOpNode*)consoleAlloc(sizeof(SlotAssignOpNode)); SlotAssignOpNode* ret = (SlotAssignOpNode*)consoleAlloc(sizeof(SlotAssignOpNode));
constructInPlace(ret); constructInPlace(ret);
ret->dbgLineNumber = lineNumber; ret->dbgLineNumber = lineNumber;
ret->optimizedNode = NULL;
ret->objectExpr = objectExpr; ret->objectExpr = objectExpr;
ret->arrayExpr = arrayExpr; ret->arrayExpr = arrayExpr;
ret->slotName = slotName; ret->slotName = slotName;
@ -410,6 +425,7 @@ ObjectDeclNode *ObjectDeclNode::alloc(S32 lineNumber, ExprNode *classNameExpr, E
ObjectDeclNode* ret = (ObjectDeclNode*)consoleAlloc(sizeof(ObjectDeclNode)); ObjectDeclNode* ret = (ObjectDeclNode*)consoleAlloc(sizeof(ObjectDeclNode));
constructInPlace(ret); constructInPlace(ret);
ret->dbgLineNumber = lineNumber; ret->dbgLineNumber = lineNumber;
ret->optimizedNode = NULL;
ret->classNameExpr = classNameExpr; ret->classNameExpr = classNameExpr;
ret->objectNameExpr = objectNameExpr; ret->objectNameExpr = objectNameExpr;
ret->argList = argList; ret->argList = argList;
@ -422,7 +438,7 @@ ObjectDeclNode *ObjectDeclNode::alloc(S32 lineNumber, ExprNode *classNameExpr, E
if (parentObject) if (parentObject)
ret->parentObject = parentObject; ret->parentObject = parentObject;
else else
ret->parentObject = StringTable->EmptyString(); ret->parentObject = StringTable->insert("");
return ret; return ret;
} }

View file

@ -50,85 +50,57 @@ namespace Compiler
ip = walk->compileStmt(codeStream, ip); ip = walk->compileStmt(codeStream, ip);
return codeStream.tell(); return codeStream.tell();
} }
inline bool isSimpleVarLookup(ExprNode *arrayExpr, StringTableEntry &varName)
{
if (arrayExpr == nullptr)
{
varName = StringTable->insert("");
return false;
}
// No double arrays allowed for optimization.
VarNode *var = dynamic_cast<VarNode*>(arrayExpr);
if (var && !var->arrayIndex)
{
StringTableEntry arrayVar = StringTable->insert(var->varName);
precompileIdent(arrayVar);
varName = arrayVar;
return true;
}
return false;
}
// Do not allow 'recursive' %this optimizations. It can lead to weird bytecode
// generation since we can only optimize one expression at a time.
static bool OnlyOneThisOptimization = false;
inline bool isThisVar(ExprNode *objectExpr)
{
// If we are currently optimizing a this var, don't allow extra optimization.
if (objectExpr == nullptr || OnlyOneThisOptimization)
return false;
VarNode *thisVar = dynamic_cast<VarNode*>(objectExpr);
if (thisVar && thisVar->varName == StringTable->insert("%this"))
return true;
return false;
}
inline void optimizeThisPointer(CodeStream &codeStream, ExprNode *arrayExpr, U32 &ip, StringTableEntry slotName)
{
OnlyOneThisOptimization = true;
// Is the array a simple variable? If so, we can optimize that.
StringTableEntry varName = nullptr;
bool simple = false;
if (arrayExpr)
{
simple = isSimpleVarLookup(arrayExpr, varName);
if (!simple)
{
// Less optimized array setting.
codeStream.emit(OP_ADVANCE_STR);
ip = arrayExpr->compile(codeStream, ip, TypeReqString);
}
}
codeStream.emit(OP_SETCURFIELD_THIS);
codeStream.emitSTE(slotName);
if (arrayExpr)
{
if (simple)
{
codeStream.emit(OP_SETCURFIELD_ARRAY_VAR);
codeStream.emitSTE(varName);
}
else
{
codeStream.emit(OP_SETCURFIELD_ARRAY);
codeStream.emit(OP_TERMINATE_REWIND_STR);
}
}
OnlyOneThisOptimization = false;
}
} }
using namespace Compiler; using namespace Compiler;
class FuncVars
{
struct Var
{
S32 reg;
TypeReq currentType;
bool isConstant;
};
public:
S32 assign(StringTableEntry var, TypeReq currentType, bool isConstant = false)
{
std::unordered_map<StringTableEntry, Var>::iterator found = vars.find(var);
if (found != vars.end())
{
AssertISV(!found->second.isConstant, avar("Reassigning variable %s when it is a constant", var));
return found->second.reg;
}
S32 id = counter++;
vars[var] = { id, currentType, isConstant };
return id;
}
S32 lookup(StringTableEntry var)
{
std::unordered_map<StringTableEntry, Var>::iterator found = vars.find(var);
AssertISV(found != vars.end(), avar("Variable %s referenced before used when compiling script.", var));
return found->second.reg;
}
TypeReq lookupType(StringTableEntry var)
{
std::unordered_map<StringTableEntry, Var>::iterator found = vars.find(var);
AssertISV(found != vars.end(), avar("Variable %s referenced before used when compiling script.", var));
return found->second.currentType;
}
inline S32 count() { return counter; }
private:
std::unordered_map<StringTableEntry, Var> vars;
S32 counter = 0;
};
FuncVars* gFuncVars = NULL;
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void StmtNode::addBreakLine(CodeStream& code) void StmtNode::addBreakLine(CodeStream& code)
@ -140,9 +112,8 @@ void StmtNode::addBreakLine(CodeStream &code)
StmtNode::StmtNode() StmtNode::StmtNode()
{ {
mNext = NULL; next = NULL;
dbgFileName = CodeBlock::smCurrentParser->getCurrentFile(); dbgFileName = CodeBlock::smCurrentParser->getCurrentFile();
dbgLineNumber = 0;
} }
void StmtNode::setPackage(StringTableEntry) void StmtNode::setPackage(StringTableEntry)
@ -152,9 +123,9 @@ void StmtNode::setPackage(StringTableEntry)
void StmtNode::append(StmtNode* next) void StmtNode::append(StmtNode* next)
{ {
StmtNode* walk = this; StmtNode* walk = this;
while (walk->mNext) while (walk->next)
walk = walk->mNext; walk = walk->next;
walk->mNext = next; walk->next = next;
} }
@ -181,8 +152,6 @@ static U32 conversionOp(TypeReq src, TypeReq dst)
return OP_STR_TO_FLT; return OP_STR_TO_FLT;
case TypeReqNone: case TypeReqNone:
return OP_STR_TO_NONE; return OP_STR_TO_NONE;
case TypeReqVar:
return OP_SAVEVAR_STR;
default: default:
break; break;
} }
@ -197,8 +166,6 @@ static U32 conversionOp(TypeReq src, TypeReq dst)
return OP_FLT_TO_STR; return OP_FLT_TO_STR;
case TypeReqNone: case TypeReqNone:
return OP_FLT_TO_NONE; return OP_FLT_TO_NONE;
case TypeReqVar:
return OP_SAVEVAR_FLT;
default: default:
break; break;
} }
@ -213,24 +180,6 @@ static U32 conversionOp(TypeReq src, TypeReq dst)
return OP_UINT_TO_STR; return OP_UINT_TO_STR;
case TypeReqNone: case TypeReqNone:
return OP_UINT_TO_NONE; return OP_UINT_TO_NONE;
case TypeReqVar:
return OP_SAVEVAR_UINT;
default:
break;
}
}
else if (src == TypeReqVar)
{
switch (dst)
{
case TypeReqUInt:
return OP_LOADVAR_UINT;
case TypeReqFloat:
return OP_LOADVAR_FLT;
case TypeReqString:
return OP_LOADVAR_STR;
case TypeReqNone:
return OP_COPYVAR_TO_NONE;
default: default:
break; break;
} }
@ -530,6 +479,12 @@ TypeReq ConditionalExprNode::getPreferredType()
U32 FloatBinaryExprNode::compile(CodeStream& codeStream, U32 ip, TypeReq type) U32 FloatBinaryExprNode::compile(CodeStream& codeStream, U32 ip, TypeReq type)
{ {
if (optimize())
{
ip = optimizedNode->compile(codeStream, ip, type);
return codeStream.tell();
}
ip = right->compile(codeStream, ip, TypeReqFloat); ip = right->compile(codeStream, ip, TypeReqFloat);
ip = left->compile(codeStream, ip, TypeReqFloat); ip = left->compile(codeStream, ip, TypeReqFloat);
U32 operand = OP_INVALID; U32 operand = OP_INVALID;
@ -619,6 +574,11 @@ void IntBinaryExprNode::getSubTypeOperand()
U32 IntBinaryExprNode::compile(CodeStream& codeStream, U32 ip, TypeReq type) U32 IntBinaryExprNode::compile(CodeStream& codeStream, U32 ip, TypeReq type)
{ {
// TODO: What if we do other optimizations and this doesn't work for it..this
// so far only works for simple MOD optimizations...
if (optimize())
right = optimizedNode;
getSubTypeOperand(); getSubTypeOperand();
if (operand == OP_OR || operand == OP_AND) if (operand == OP_OR || operand == OP_AND)
@ -767,13 +727,7 @@ TypeReq FloatUnaryExprNode::getPreferredType()
U32 VarNode::compile(CodeStream& codeStream, U32 ip, TypeReq type) U32 VarNode::compile(CodeStream& codeStream, U32 ip, TypeReq type)
{ {
// if this has an arrayIndex and we are not short circuiting from a constant. // if this has an arrayIndex...
// if we are a var node
// OP_SETCURVAR_ARRAY_VARLOOKUP
// varName
// varNodeVarName
// else
// OP_LOADIMMED_IDENT // OP_LOADIMMED_IDENT
// varName // varName
// OP_ADVANCE_STR // OP_ADVANCE_STR
@ -790,54 +744,22 @@ U32 VarNode::compile(CodeStream &codeStream, U32 ip, TypeReq type)
if (type == TypeReqNone) if (type == TypeReqNone)
return codeStream.tell(); return codeStream.tell();
bool shortCircuit = false;
if (arrayIndex)
{
// If we have a constant, shortcircuit the array logic.
IntNode *intNode = dynamic_cast<IntNode*>(arrayIndex);
StrConstNode *strNode = dynamic_cast<StrConstNode*>(arrayIndex);
if (intNode)
{
varName = StringTable->insert(avar("%s%d", varName, intNode->value));
shortCircuit = true;
}
else if (strNode)
{
varName = StringTable->insert(avar("%s%s", varName, strNode->str));
shortCircuit = true;
}
}
precompileIdent(varName); precompileIdent(varName);
if (arrayIndex && !shortCircuit) bool oldVariables = arrayIndex || varName[0] == '$';
if (oldVariables)
{ {
// Ok, lets try to optimize %var[%someothervar] as this is codeStream.emit(arrayIndex ? OP_LOADIMMED_IDENT : OP_SETCURVAR);
// a common case for array usage.
StringTableEntry varNodeVarName;
if (isSimpleVarLookup(arrayIndex, varNodeVarName))
{
codeStream.emit(OP_SETCURVAR_ARRAY_VARLOOKUP);
codeStream.emitSTE(varName); codeStream.emitSTE(varName);
codeStream.emitSTE(varNodeVarName);
} if (arrayIndex)
else
{ {
codeStream.emit(OP_LOADIMMED_IDENT);
codeStream.emitSTE(varName);
codeStream.emit(OP_ADVANCE_STR); codeStream.emit(OP_ADVANCE_STR);
ip = arrayIndex->compile(codeStream, ip, TypeReqString); ip = arrayIndex->compile(codeStream, ip, TypeReqString);
codeStream.emit(OP_REWIND_STR); codeStream.emit(OP_REWIND_STR);
codeStream.emit(OP_SETCURVAR_ARRAY); codeStream.emit(OP_SETCURVAR_ARRAY);
} }
}
else
{
codeStream.emit(OP_SETCURVAR);
codeStream.emitSTE(varName);
}
switch (type) switch (type)
{ {
case TypeReqUInt: case TypeReqUInt:
@ -849,20 +771,31 @@ U32 VarNode::compile(CodeStream &codeStream, U32 ip, TypeReq type)
case TypeReqString: case TypeReqString:
codeStream.emit(OP_LOADVAR_STR); codeStream.emit(OP_LOADVAR_STR);
break; break;
case TypeReqVar:
codeStream.emit(OP_LOADVAR_VAR);
break;
case TypeReqNone: case TypeReqNone:
break; break;
default: default:
break; break;
} }
}
else
{
switch (type)
{
case TypeReqUInt: codeStream.emit(OP_LOAD_LOCAL_VAR_UINT); break;
case TypeReqFloat: codeStream.emit(OP_LOAD_LOCAL_VAR_FLT); break;
default: codeStream.emit(OP_LOAD_LOCAL_VAR_STR);
}
codeStream.emit(gFuncVars->lookup(varName));
}
return codeStream.tell(); return codeStream.tell();
} }
TypeReq VarNode::getPreferredType() TypeReq VarNode::getPreferredType()
{ {
return TypeReqNone; // no preferred type bool oldVariables = arrayIndex || varName[0] == '$';
return oldVariables ? TypeReqNone : gFuncVars->lookupType(varName);
} }
//------------------------------------------------------------ //------------------------------------------------------------
@ -1037,43 +970,17 @@ U32 AssignExprNode::compile(CodeStream &codeStream, U32 ip, TypeReq type)
if (subType == TypeReqNone) if (subType == TypeReqNone)
subType = type; subType = type;
if (subType == TypeReqNone) if (subType == TypeReqNone)
{
// What we need to do in this case is turn it into a VarNode reference.
// Unfortunately other nodes such as field access (SlotAccessNode)
// cannot be optimized in the same manner as all fields are exposed
// and set as strings.
if (dynamic_cast<VarNode*>(expr) != NULL)
{
subType = TypeReqVar;
}
else
{
subType = TypeReqString; subType = TypeReqString;
}
}
//if we are an array index and we are gonna short circuit // if it's an array expr, the formula is:
// eval expr
// compute new varName
// OP_SETCURVAR_CREATE
// varName
// OP_SAVEVAR
//else if it's an array expr and we don't short circuit, the formula is:
// eval expr // eval expr
// (push and pop if it's TypeReqString) OP_ADVANCE_STR // (push and pop if it's TypeReqString) OP_ADVANCE_STR
// if array lookup is varnode
// OP_SETCURVAR_ARRAY_CREATE_VARLOOKUP
// varName
// varNodeVarName
// else
// OP_LOADIMMED_IDENT // OP_LOADIMMED_IDENT
// varName // varName
// OP_ADVANCE_STR // OP_ADVANCE_STR
// eval array // eval array
// OP_REWIND_STR // OP_REWIND_STR
// OP_SETCURVAR_ARRAY_CREATE // OP_SETCURVAR_ARRAY_CREATE
// endif
// OP_TERMINATE_REWIND_STR // OP_TERMINATE_REWIND_STR
// OP_SAVEVAR // OP_SAVEVAR
@ -1083,45 +990,19 @@ U32 AssignExprNode::compile(CodeStream &codeStream, U32 ip, TypeReq type)
// varname // varname
// OP_SAVEVAR // OP_SAVEVAR
ip = expr->compile(codeStream, ip, subType);
bool shortCircuit = false;
if (arrayIndex)
{
// If we have a constant, shortcircuit the array logic.
IntNode *intNode = dynamic_cast<IntNode*>(arrayIndex);
StrConstNode *strNode = dynamic_cast<StrConstNode*>(arrayIndex);
if (intNode)
{
varName = StringTable->insert(avar("%s%d", varName, intNode->value));
shortCircuit = true;
}
else if (strNode)
{
varName = StringTable->insert(avar("%s%s", varName, strNode->str));
shortCircuit = true;
}
}
precompileIdent(varName); precompileIdent(varName);
if (arrayIndex && !shortCircuit) ip = expr->compile(codeStream, ip, subType);
bool oldVariables = arrayIndex || varName[0] == '$';
if (oldVariables)
{
if (arrayIndex)
{ {
if (subType == TypeReqString) if (subType == TypeReqString)
codeStream.emit(OP_ADVANCE_STR); codeStream.emit(OP_ADVANCE_STR);
// Ok, lets try to optimize %var[%someothervar] as this is
// a common case for array usage.
StringTableEntry varNodeVarName;
if (isSimpleVarLookup(arrayIndex, varNodeVarName))
{
codeStream.emit(OP_SETCURVAR_ARRAY_CREATE_VARLOOKUP);
codeStream.emitSTE(varName);
codeStream.emitSTE(varNodeVarName);
}
else
{
codeStream.emit(OP_LOADIMMED_IDENT); codeStream.emit(OP_LOADIMMED_IDENT);
codeStream.emitSTE(varName); codeStream.emitSTE(varName);
@ -1129,8 +1010,6 @@ U32 AssignExprNode::compile(CodeStream &codeStream, U32 ip, TypeReq type)
ip = arrayIndex->compile(codeStream, ip, TypeReqString); ip = arrayIndex->compile(codeStream, ip, TypeReqString);
codeStream.emit(OP_REWIND_STR); codeStream.emit(OP_REWIND_STR);
codeStream.emit(OP_SETCURVAR_ARRAY_CREATE); codeStream.emit(OP_SETCURVAR_ARRAY_CREATE);
}
if (subType == TypeReqString) if (subType == TypeReqString)
codeStream.emit(OP_TERMINATE_REWIND_STR); codeStream.emit(OP_TERMINATE_REWIND_STR);
} }
@ -1141,23 +1020,27 @@ U32 AssignExprNode::compile(CodeStream &codeStream, U32 ip, TypeReq type)
} }
switch (subType) switch (subType)
{ {
case TypeReqString: case TypeReqString: codeStream.emit(OP_SAVEVAR_STR); break;
codeStream.emit(OP_SAVEVAR_STR); case TypeReqUInt: codeStream.emit(OP_SAVEVAR_UINT); break;
break; case TypeReqFloat: codeStream.emit(OP_SAVEVAR_FLT); break;
case TypeReqUInt:
codeStream.emit(OP_SAVEVAR_UINT);
break;
case TypeReqFloat:
codeStream.emit(OP_SAVEVAR_FLT);
break;
case TypeReqVar:
codeStream.emit(OP_SAVEVAR_VAR);
break;
case TypeReqNone:
break;
} }
}
else
{
switch (subType)
{
case TypeReqUInt: codeStream.emit(OP_SAVE_LOCAL_VAR_UINT); break;
case TypeReqFloat: codeStream.emit(OP_SAVE_LOCAL_VAR_FLT); break;
default: codeStream.emit(OP_SAVE_LOCAL_VAR_STR);
}
codeStream.emit(gFuncVars->assign(varName, subType == TypeReqNone ? TypeReqString : subType));
}
if (type != subType) if (type != subType)
codeStream.emit(conversionOp(subType, type)); {
U32 conOp = conversionOp(subType, type);
codeStream.emit(conOp);
}
return ip; return ip;
} }
@ -1178,7 +1061,6 @@ static void getAssignOpTypeOp(S32 op, TypeReq &type, U32 &operand)
operand = OP_ADD; operand = OP_ADD;
break; break;
case '-': case '-':
case opMINUSMINUS:
type = TypeReqFloat; type = TypeReqFloat;
operand = OP_SUB; operand = OP_SUB;
break; break;
@ -1221,112 +1103,49 @@ U32 AssignOpExprNode::compile(CodeStream &codeStream, U32 ip, TypeReq type)
{ {
// goes like this... // goes like this...
//
// IF no array index && (op == OPPLUSPLUS or op == OPMINUSMINUS)
// if op == OPPLUSPLUS
// OP_INC
// varName
// else if op == OPMINUSMINUS
// OP_DEC
// varName
// else
// OP_INVALID
// endif
// ELSE
// eval expr as float or int // eval expr as float or int
// if there's an arrayIndex and we don't short circuit // if there's an arrayIndex
// if arrayIndex is a var node
// OP_SETCURVAR_ARRAY_CREATE_VARLOOKUP
// varName
// varNodeVarName
// else
// OP_LOADIMMED_IDENT // OP_LOADIMMED_IDENT
// varName // varName
// OP_ADVANCE_STR // OP_ADVANCE_STR
// eval arrayIndex stringwise // eval arrayIndex stringwise
// OP_REWIND_STR // OP_REWIND_STR
// OP_SETCURVAR_ARRAY_CREATE // OP_SETCURVAR_ARRAY_CREATE
// endif
// else // else
// OP_SETCURVAR_CREATE // OP_SETCURVAR_CREATE
// varName // varName
// endif
// OP_LOADVAR_FLT or UINT // OP_LOADVAR_FLT or UINT
// operand // operand
// OP_SAVEVAR_FLT or UINT // OP_SAVEVAR_FLT or UINT
// ENDIF
//
// if subtype != type
// convert type
// endif
// conversion OP if necessary. // conversion OP if necessary.
getAssignOpTypeOp(op, subType, operand); getAssignOpTypeOp(op, subType, operand);
// ++ or -- optimization support for non indexed variables.
if ((!arrayIndex) && (op == opPLUSPLUS || op == opMINUSMINUS))
{
precompileIdent(varName); precompileIdent(varName);
if (op == opPLUSPLUS) bool oldVariables = arrayIndex || varName[0] == '$';
if (op == opPLUSPLUS && !oldVariables)
{ {
const S32 varIdx = gFuncVars->assign(varName, TypeReqFloat);
codeStream.emit(OP_INC); codeStream.emit(OP_INC);
codeStream.emitSTE(varName); codeStream.emit(varIdx);
}
else if (op == opMINUSMINUS)
{
codeStream.emit(OP_DEC);
codeStream.emitSTE(varName);
}
else
{
// This should NEVER happen. This is just for sanity.
AssertISV(false, "Tried to use ++ or -- but something weird happened.");
codeStream.emit(OP_INVALID);
}
} }
else else
{ {
ip = expr->compile(codeStream, ip, subType); ip = expr->compile(codeStream, ip, subType);
bool shortCircuit = false; if (oldVariables)
if (arrayIndex)
{ {
// If we have a constant, shortcircuit the array logic. if (!arrayIndex)
IntNode *intNode = dynamic_cast<IntNode*>(arrayIndex);
StrConstNode *strNode = dynamic_cast<StrConstNode*>(arrayIndex);
if (intNode)
{
varName = StringTable->insert(avar("%s%d", varName, intNode->value));
shortCircuit = true;
}
else if (strNode)
{
varName = StringTable->insert(avar("%s%s", varName, strNode->str));
shortCircuit = true;
}
}
precompileIdent(varName);
if (!arrayIndex || shortCircuit)
{ {
codeStream.emit(OP_SETCURVAR_CREATE); codeStream.emit(OP_SETCURVAR_CREATE);
codeStream.emitSTE(varName); codeStream.emitSTE(varName);
} }
else else
{
// Ok, lets try to optimize %var[%someothervar] as this is
// a common case for array usage.
StringTableEntry varNodeVarName;
if (isSimpleVarLookup(arrayIndex, varNodeVarName))
{
codeStream.emit(OP_SETCURVAR_ARRAY_CREATE_VARLOOKUP);
codeStream.emitSTE(varName);
codeStream.emitSTE(varNodeVarName);
}
else
{ {
codeStream.emit(OP_LOADIMMED_IDENT); codeStream.emit(OP_LOADIMMED_IDENT);
codeStream.emitSTE(varName); codeStream.emitSTE(varName);
@ -1336,13 +1155,27 @@ U32 AssignOpExprNode::compile(CodeStream &codeStream, U32 ip, TypeReq type)
codeStream.emit(OP_REWIND_STR); codeStream.emit(OP_REWIND_STR);
codeStream.emit(OP_SETCURVAR_ARRAY_CREATE); codeStream.emit(OP_SETCURVAR_ARRAY_CREATE);
} }
}
codeStream.emit((subType == TypeReqFloat) ? OP_LOADVAR_FLT : OP_LOADVAR_UINT); codeStream.emit((subType == TypeReqFloat) ? OP_LOADVAR_FLT : OP_LOADVAR_UINT);
codeStream.emit(operand); codeStream.emit(operand);
codeStream.emit((subType == TypeReqFloat) ? OP_SAVEVAR_FLT : OP_SAVEVAR_UINT); codeStream.emit((subType == TypeReqFloat) ? OP_SAVEVAR_FLT : OP_SAVEVAR_UINT);
} }
else
{
const bool isFloat = subType == TypeReqFloat;
const S32 varIdx = gFuncVars->assign(varName, subType == TypeReqNone ? TypeReqString : subType);
codeStream.emit(isFloat ? OP_LOAD_LOCAL_VAR_FLT : OP_LOAD_LOCAL_VAR_UINT);
codeStream.emit(varIdx);
codeStream.emit(operand);
codeStream.emit(isFloat ? OP_SAVE_LOCAL_VAR_FLT : OP_SAVE_LOCAL_VAR_UINT);
codeStream.emit(varIdx);
}
if (subType != type) if (subType != type)
{
codeStream.emit(conversionOp(subType, type)); codeStream.emit(conversionOp(subType, type));
}
}
return codeStream.tell(); return codeStream.tell();
} }
@ -1399,38 +1232,19 @@ U32 FuncCallExprNode::compile(CodeStream &codeStream, U32 ip, TypeReq type)
precompileIdent(funcName); precompileIdent(funcName);
precompileIdent(nameSpace); precompileIdent(nameSpace);
S32 count = 0;
for (ExprNode* walk = args; walk; walk = static_cast<ExprNode*>(walk->getNext()))
count++;
codeStream.emit(OP_PUSH_FRAME); codeStream.emit(OP_PUSH_FRAME);
codeStream.emit(count);
bool isThisCall = false; for (ExprNode* walk = args; walk; walk = static_cast<ExprNode*>(walk->getNext()))
ExprNode *walk = args;
// Try to optimize the this pointer call if it is a variable
// that we are loading.
if (callType == MethodCall)
{
// We cannot optimize array indices because it can have quite
// a bit of code to figure out the array index.
VarNode *var = dynamic_cast<VarNode*>(args);
if (var && !var->arrayIndex)
{
precompileIdent(var->varName);
// Are we a %this call?
isThisCall = (var->varName == StringTable->insert("%this"));
codeStream.emit(OP_PUSH_THIS);
codeStream.emitSTE(var->varName);
// inc args since we took care of first arg.
walk = (ExprNode*)walk ->getNext();
}
}
for (; walk; walk = (ExprNode *)walk->getNext())
{ {
TypeReq walkType = walk->getPreferredType(); TypeReq walkType = walk->getPreferredType();
if (walkType == TypeReqNone) walkType = TypeReqString; if (walkType == TypeReqNone)
walkType = TypeReqString;
ip = walk->compile(codeStream, ip, walkType); ip = walk->compile(codeStream, ip, walkType);
switch (walk->getPreferredType()) switch (walk->getPreferredType())
{ {
@ -1446,22 +1260,10 @@ U32 FuncCallExprNode::compile(CodeStream &codeStream, U32 ip, TypeReq type)
} }
} }
if (isThisCall)
{
codeStream.emit(OP_CALLFUNC_THIS);
codeStream.emitSTE(funcName);
}
else
{
if (callType == MethodCall || callType == ParentCall)
codeStream.emit(OP_CALLFUNC); codeStream.emit(OP_CALLFUNC);
else
codeStream.emit(OP_CALLFUNC_RESOLVE);
codeStream.emitSTE(funcName); codeStream.emitSTE(funcName);
codeStream.emitSTE(nameSpace); codeStream.emitSTE(nameSpace);
codeStream.emit(callType); codeStream.emit(callType);
}
if (type != TypeReqString) if (type != TypeReqString)
codeStream.emit(conversionOp(TypeReqString, type)); codeStream.emit(conversionOp(TypeReqString, type));
@ -1473,49 +1275,6 @@ TypeReq FuncCallExprNode::getPreferredType()
return TypeReqString; return TypeReqString;
} }
//------------------------------------------------------------
U32 FuncPointerCallExprNode::compile(CodeStream &codeStream, U32 ip, TypeReq type)
{
// OP_PUSH_FRAME
// arg OP_PUSH arg OP_PUSH arg OP_PUSH
// eval all the args, then call the function.
// eval fn pointer
// OP_CALLFUNC_POINTER
codeStream.emit(OP_PUSH_FRAME);
for (ExprNode *walk = args; walk; walk = (ExprNode *)walk->getNext())
{
TypeReq walkType = walk->getPreferredType();
if (walkType == TypeReqNone) walkType = TypeReqString;
ip = walk->compile(codeStream, ip, walkType);
switch (walk->getPreferredType())
{
case TypeReqFloat:
codeStream.emit(OP_PUSH_FLT);
break;
case TypeReqUInt:
codeStream.emit(OP_PUSH_UINT);
break;
default:
codeStream.emit(OP_PUSH);
break;
}
}
ip = funcPointer->compile(codeStream, ip, TypeReqString);
codeStream.emit(OP_CALLFUNC_POINTER);
if (type != TypeReqString)
codeStream.emit(conversionOp(TypeReqString, type));
return codeStream.tell();
}
TypeReq FuncPointerCallExprNode::getPreferredType()
{
return TypeReqString;
}
//------------------------------------------------------------ //------------------------------------------------------------
@ -1548,13 +1307,6 @@ U32 SlotAccessNode::compile(CodeStream &codeStream, U32 ip, TypeReq type)
precompileIdent(slotName); precompileIdent(slotName);
// check if object is %this. If we are, we can do additional optimizations.
if (isThisVar(objectExpr))
{
optimizeThisPointer(codeStream, arrayExpr, ip, slotName);
}
else
{
if (arrayExpr) if (arrayExpr)
{ {
// eval array // eval array
@ -1579,7 +1331,6 @@ U32 SlotAccessNode::compile(CodeStream &codeStream, U32 ip, TypeReq type)
codeStream.emit(OP_TERMINATE_REWIND_STR); codeStream.emit(OP_TERMINATE_REWIND_STR);
codeStream.emit(OP_SETCURFIELD_ARRAY); codeStream.emit(OP_SETCURFIELD_ARRAY);
} }
}
switch (type) switch (type)
{ {
@ -1662,13 +1413,6 @@ U32 SlotAssignNode::compile(CodeStream &codeStream, U32 ip, TypeReq type)
precompileIdent(slotName); precompileIdent(slotName);
ip = valueExpr->compile(codeStream, ip, TypeReqString); ip = valueExpr->compile(codeStream, ip, TypeReqString);
if (isThisVar(objectExpr))
{
optimizeThisPointer(codeStream, arrayExpr, ip, slotName);
}
else
{
codeStream.emit(OP_ADVANCE_STR); codeStream.emit(OP_ADVANCE_STR);
if (arrayExpr) if (arrayExpr)
{ {
@ -1692,8 +1436,6 @@ U32 SlotAssignNode::compile(CodeStream &codeStream, U32 ip, TypeReq type)
} }
codeStream.emit(OP_TERMINATE_REWIND_STR); codeStream.emit(OP_TERMINATE_REWIND_STR);
}
codeStream.emit(OP_SAVEFIELD_STR); codeStream.emit(OP_SAVEFIELD_STR);
if (typeID != -1) if (typeID != -1)
@ -1743,13 +1485,6 @@ U32 SlotAssignOpNode::compile(CodeStream &codeStream, U32 ip, TypeReq type)
precompileIdent(slotName); precompileIdent(slotName);
ip = valueExpr->compile(codeStream, ip, subType); ip = valueExpr->compile(codeStream, ip, subType);
if (isThisVar(objectExpr))
{
optimizeThisPointer(codeStream, arrayExpr, ip, slotName);
}
else
{
if (arrayExpr) if (arrayExpr)
{ {
ip = arrayExpr->compile(codeStream, ip, TypeReqString); ip = arrayExpr->compile(codeStream, ip, TypeReqString);
@ -1765,7 +1500,6 @@ U32 SlotAssignOpNode::compile(CodeStream &codeStream, U32 ip, TypeReq type)
codeStream.emit(OP_TERMINATE_REWIND_STR); codeStream.emit(OP_TERMINATE_REWIND_STR);
codeStream.emit(OP_SETCURFIELD_ARRAY); codeStream.emit(OP_SETCURFIELD_ARRAY);
} }
}
codeStream.emit((subType == TypeReqFloat) ? OP_LOADFIELD_FLT : OP_LOADFIELD_UINT); codeStream.emit((subType == TypeReqFloat) ? OP_LOADFIELD_FLT : OP_LOADFIELD_UINT);
codeStream.emit(operand); codeStream.emit(operand);
codeStream.emit((subType == TypeReqFloat) ? OP_SAVEFIELD_FLT : OP_SAVEFIELD_UINT); codeStream.emit((subType == TypeReqFloat) ? OP_SAVEFIELD_FLT : OP_SAVEFIELD_UINT);
@ -1808,7 +1542,12 @@ U32 ObjectDeclNode::compileSubObject(CodeStream &codeStream, U32 ip, bool root)
// To fix the stack issue [7/9/2007 Black] // To fix the stack issue [7/9/2007 Black]
// OP_FINISH_OBJECT <-- fail point jumps to this opcode // OP_FINISH_OBJECT <-- fail point jumps to this opcode
S32 count = 2; // 2 OP_PUSH's
for (ExprNode* exprWalk = argList; exprWalk; exprWalk = (ExprNode*)exprWalk->getNext())
count++;
codeStream.emit(OP_PUSH_FRAME); codeStream.emit(OP_PUSH_FRAME);
codeStream.emit(count);
ip = classNameExpr->compile(codeStream, ip, TypeReqString); ip = classNameExpr->compile(codeStream, ip, TypeReqString);
codeStream.emit(OP_PUSH); codeStream.emit(OP_PUSH);
@ -1896,10 +1635,14 @@ U32 FunctionDeclStmtNode::compileStmt(CodeStream &codeStream, U32 ip)
setCurrentStringTable(&getFunctionStringTable()); setCurrentStringTable(&getFunctionStringTable());
setCurrentFloatTable(&getFunctionFloatTable()); setCurrentFloatTable(&getFunctionFloatTable());
FuncVars vars;
gFuncVars = &vars;
argc = 0; argc = 0;
for (VarNode* walk = args; walk; walk = (VarNode*)((StmtNode*)walk)->getNext()) for (VarNode* walk = args; walk; walk = (VarNode*)((StmtNode*)walk)->getNext())
{ {
precompileIdent(walk->varName); precompileIdent(walk->varName);
gFuncVars->assign(walk->varName, TypeReqNone);
argc++; argc++;
} }
@ -1919,9 +1662,11 @@ U32 FunctionDeclStmtNode::compileStmt(CodeStream &codeStream, U32 ip)
codeStream.emit(U32(bool(stmts != NULL) ? 1 : 0) + U32(dbgLineNumber << 1)); codeStream.emit(U32(bool(stmts != NULL) ? 1 : 0) + U32(dbgLineNumber << 1));
const U32 endIp = codeStream.emit(0); const U32 endIp = codeStream.emit(0);
codeStream.emit(argc); codeStream.emit(argc);
const U32 localNumVarsIP = codeStream.emit(0);
for (VarNode* walk = args; walk; walk = (VarNode*)((StmtNode*)walk)->getNext()) for (VarNode* walk = args; walk; walk = (VarNode*)((StmtNode*)walk)->getNext())
{ {
codeStream.emitSTE(walk->varName); StringTableEntry name = walk->varName;
codeStream.emit(gFuncVars->lookup(name));
} }
CodeBlock::smInFunction = true; CodeBlock::smInFunction = true;
ip = compileBlock(stmts, codeStream, ip); ip = compileBlock(stmts, codeStream, ip);
@ -1933,10 +1678,12 @@ U32 FunctionDeclStmtNode::compileStmt(CodeStream &codeStream, U32 ip)
CodeBlock::smInFunction = false; CodeBlock::smInFunction = false;
codeStream.emit(OP_RETURN_VOID); codeStream.emit(OP_RETURN_VOID);
codeStream.patch(localNumVarsIP, gFuncVars->count());
codeStream.patch(endIp, codeStream.tell()); codeStream.patch(endIp, codeStream.tell());
setCurrentStringTable(&getGlobalStringTable()); setCurrentStringTable(&getGlobalStringTable());
setCurrentFloatTable(&getGlobalFloatTable()); setCurrentFloatTable(&getGlobalFloatTable());
gFuncVars = NULL;
return ip; return ip;
} }

View file

@ -477,7 +477,6 @@ bool CodeBlock::compile(const char *codeFileName, StringTableEntry fileName, con
STEtoCode = compileSTEtoCode; STEtoCode = compileSTEtoCode;
gStatementList = NULL; gStatementList = NULL;
gAnonFunctionList = NULL;
// Set up the parser. // Set up the parser.
smCurrentParser = getParserForFile(fileName); smCurrentParser = getParserForFile(fileName);
@ -487,17 +486,6 @@ bool CodeBlock::compile(const char *codeFileName, StringTableEntry fileName, con
smCurrentParser->setScanBuffer(script, fileName); smCurrentParser->setScanBuffer(script, fileName);
smCurrentParser->restart(NULL); smCurrentParser->restart(NULL);
smCurrentParser->parse(); smCurrentParser->parse();
if (gStatementList)
{
if (gAnonFunctionList)
{
// Prepend anonymous functions to statement list, so they're defined already when
// the statements run.
gAnonFunctionList->append(gStatementList);
gStatementList = gAnonFunctionList;
}
}
if (gSyntaxError) if (gSyntaxError)
{ {
@ -575,11 +563,9 @@ bool CodeBlock::compile(const char *codeFileName, StringTableEntry fileName, con
st.close(); st.close();
return true; return true;
} }
ConsoleValueRef CodeBlock::compileExec(StringTableEntry fileName, const char *inString, bool noCalls, S32 setFrame) void CodeBlock::compileExec(StringTableEntry fileName, const char *inString, ConsoleValue &returnValue, bool noCalls, S32 setFrame)
{ {
AssertFatal(Con::isMainThread(), "Compiling code on a secondary thread"); AssertFatal(Con::isMainThread(), "Compiling code on a secondary thread");
@ -620,7 +606,6 @@ ConsoleValueRef CodeBlock::compileExec(StringTableEntry fileName, const char *in
addToCodeList(); addToCodeList();
gStatementList = NULL; gStatementList = NULL;
gAnonFunctionList = NULL;
// Set up the parser. // Set up the parser.
smCurrentParser = getParserForFile(fileName); smCurrentParser = getParserForFile(fileName);
@ -630,21 +615,11 @@ ConsoleValueRef CodeBlock::compileExec(StringTableEntry fileName, const char *in
smCurrentParser->setScanBuffer(string, fileName); smCurrentParser->setScanBuffer(string, fileName);
smCurrentParser->restart(NULL); smCurrentParser->restart(NULL);
smCurrentParser->parse(); smCurrentParser->parse();
if (gStatementList)
{
if (gAnonFunctionList)
{
// Prepend anonymous functions to statement list, so they're defined already when
// the statements run.
gAnonFunctionList->append(gStatementList);
gStatementList = gAnonFunctionList;
}
}
if (!gStatementList) if (!gStatementList)
{ {
delete this; delete this;
return ConsoleValueRef(); return;
} }
resetTables(); resetTables();
@ -678,7 +653,7 @@ ConsoleValueRef CodeBlock::compileExec(StringTableEntry fileName, const char *in
if (lastIp + 1 != codeSize) if (lastIp + 1 != codeSize)
Con::warnf(ConsoleLogEntry::General, "precompile size mismatch, precompile: %d compile: %d", codeSize, lastIp); Con::warnf(ConsoleLogEntry::General, "precompile size mismatch, precompile: %d compile: %d", codeSize, lastIp);
return exec(0, fileName, NULL, 0, 0, noCalls, NULL, setFrame); exec(0, fileName, NULL, 0, 0, noCalls, NULL, returnValue, setFrame);
} }
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
@ -747,14 +722,15 @@ void CodeBlock::dumpInstructions(U32 startIp, bool upToReturn)
bool hasBody = bool(code[ip + 6]); bool hasBody = bool(code[ip + 6]);
U32 newIp = code[ip + 7]; U32 newIp = code[ip + 7];
U32 argc = code[ip + 8]; U32 argc = code[ip + 8];
U32 regCount = code[ip + 9];
endFuncIp = newIp; endFuncIp = newIp;
Con::printf("%i: OP_FUNC_DECL name=%s nspace=%s package=%s hasbody=%i newip=%i argc=%i", Con::printf("%i: OP_FUNC_DECL name=%s nspace=%s package=%s hasbody=%i newip=%i argc=%i regCount=%i",
ip - 1, fnName, fnNamespace, fnPackage, hasBody, newIp, argc); ip - 1, fnName, fnNamespace, fnPackage, hasBody, newIp, argc, regCount);
// Skip args. // Skip args.
ip += 9 + (argc * 2); ip += 10 + argc;
smInFunction = true; smInFunction = true;
break; break;
} }
@ -1018,15 +994,8 @@ void CodeBlock::dumpInstructions(U32 startIp, bool upToReturn)
case OP_INC: case OP_INC:
{ {
Con::printf("%i: OP_INC varName=%s", ip - 1, CodeToSTE(code, ip)); Con::printf("%i: OP_INC reg=%i", ip - 1, code[ip]);
ip += 2; ++ip;
break;
}
case OP_DEC:
{
Con::printf("%i: OP_DEC varName=%s", ip - 1, CodeToSTE(code, ip));
ip += 2;
break; break;
} }
@ -1054,32 +1023,12 @@ void CodeBlock::dumpInstructions(U32 startIp, bool upToReturn)
break; break;
} }
case OP_SETCURVAR_ARRAY_VARLOOKUP:
{
StringTableEntry arrayName = CodeToSTE(code, ip);
StringTableEntry arrayLookup = CodeToSTE(code, ip + 2);
Con::printf("%i: OP_SETCURVAR_ARRAY_VARLOOKUP arrayName=%s arrayLookup=%s", ip - 1, arrayName, arrayLookup);
ip += 4;
break;
}
case OP_SETCURVAR_ARRAY_CREATE: case OP_SETCURVAR_ARRAY_CREATE:
{ {
Con::printf("%i: OP_SETCURVAR_ARRAY_CREATE", ip - 1); Con::printf("%i: OP_SETCURVAR_ARRAY_CREATE", ip - 1);
break; break;
} }
case OP_SETCURVAR_ARRAY_CREATE_VARLOOKUP:
{
StringTableEntry arrayName = CodeToSTE(code, ip);
StringTableEntry arrayLookup = CodeToSTE(code, ip + 2);
Con::printf("%i: OP_SETCURVAR_ARRAY_CREATE_VARLOOKUP arrayName=%s arrayLookup=%s", ip - 1, arrayName, arrayLookup);
ip += 4;
break;
}
case OP_LOADVAR_UINT: case OP_LOADVAR_UINT:
{ {
Con::printf("%i: OP_LOADVAR_UINT", ip - 1); Con::printf("%i: OP_LOADVAR_UINT", ip - 1);
@ -1098,12 +1047,6 @@ void CodeBlock::dumpInstructions(U32 startIp, bool upToReturn)
break; break;
} }
case OP_LOADVAR_VAR:
{
Con::printf("%i: OP_LOADVAR_VAR", ip - 1);
break;
}
case OP_SAVEVAR_UINT: case OP_SAVEVAR_UINT:
{ {
Con::printf("%i: OP_SAVEVAR_UINT", ip - 1); Con::printf("%i: OP_SAVEVAR_UINT", ip - 1);
@ -1122,9 +1065,45 @@ void CodeBlock::dumpInstructions(U32 startIp, bool upToReturn)
break; break;
} }
case OP_SAVEVAR_VAR: case OP_LOAD_LOCAL_VAR_UINT:
{ {
Con::printf("%i: OP_SAVEVAR_VAR", ip - 1); Con::printf("%i: OP_LOAD_LOCAL_VAR_UINT reg=%i", ip - 1, code[ip]);
++ip;
break;
}
case OP_LOAD_LOCAL_VAR_FLT:
{
Con::printf("%i: OP_LOAD_LOCAL_VAR_FLT reg=%i", ip - 1, code[ip]);
++ip;
break;
}
case OP_LOAD_LOCAL_VAR_STR:
{
Con::printf("%i: OP_LOAD_LOCAL_VAR_STR reg=%i", ip - 1, code[ip]);
++ip;
break;
}
case OP_SAVE_LOCAL_VAR_UINT:
{
Con::printf("%i: OP_SAVE_LOCAL_VAR_UINT reg=%i", ip - 1, code[ip]);
++ip;
break;
}
case OP_SAVE_LOCAL_VAR_FLT:
{
Con::printf("%i: OP_SAVE_LOCAL_VAR_FLT reg=%i", ip - 1, code[ip]);
++ip;
break;
}
case OP_SAVE_LOCAL_VAR_STR:
{
Con::printf("%i: OP_SAVE_LOCAL_VAR_STR reg=%i", ip - 1, code[ip]);
++ip;
break; break;
} }
@ -1161,22 +1140,6 @@ void CodeBlock::dumpInstructions(U32 startIp, bool upToReturn)
break; break;
} }
case OP_SETCURFIELD_ARRAY_VAR:
{
StringTableEntry var = CodeToSTE(code, ip);
Con::printf("%i: OP_SETCURFIELD_ARRAY_VAR var=%s", ip - 1, var);
ip += 2;
break;
}
case OP_SETCURFIELD_THIS:
{
StringTableEntry curField = CodeToSTE(code, ip);
Con::printf("%i: OP_SETCURFIELD_THIS field=%s", ip - 1, curField);
ip += 2;
break;
}
case OP_SETCURFIELD_TYPE: case OP_SETCURFIELD_TYPE:
{ {
U32 type = code[ip]; U32 type = code[ip];
@ -1259,7 +1222,7 @@ void CodeBlock::dumpInstructions(U32 startIp, bool upToReturn)
case OP_UINT_TO_FLT: case OP_UINT_TO_FLT:
{ {
Con::printf("%i: OP_SAVEFIELD_STR", ip - 1); Con::printf("%i: OP_UINT_TO_FLT", ip - 1);
break; break;
} }
@ -1275,12 +1238,6 @@ void CodeBlock::dumpInstructions(U32 startIp, bool upToReturn)
break; break;
} }
case OP_COPYVAR_TO_NONE:
{
Con::printf("%i: OP_COPYVAR_TO_NONE", ip - 1);
break;
}
case OP_LOADIMMED_UINT: case OP_LOADIMMED_UINT:
{ {
U32 val = code[ip]; U32 val = code[ip];
@ -1329,49 +1286,27 @@ void CodeBlock::dumpInstructions(U32 startIp, bool upToReturn)
break; break;
} }
case OP_CALLFUNC_RESOLVE:
{
StringTableEntry fnNamespace = CodeToSTE(code, ip + 2);
StringTableEntry fnName = CodeToSTE(code, ip);
U32 callType = code[ip + 2];
Con::printf("%i: OP_CALLFUNC_RESOLVE name=%s nspace=%s callType=%s", ip - 1, fnName, fnNamespace,
callType == FuncCallExprNode::FunctionCall ? "FunctionCall"
: callType == FuncCallExprNode::MethodCall ? "MethodCall" : "ParentCall");
ip += 5;
break;
}
case OP_CALLFUNC: case OP_CALLFUNC:
{ {
StringTableEntry fnNamespace = CodeToSTE(code, ip + 2); StringTableEntry fnNamespace = CodeToSTE(code, ip + 2);
StringTableEntry fnName = CodeToSTE(code, ip); StringTableEntry fnName = CodeToSTE(code, ip);
U32 callType = code[ip + 4]; U32 callType = code[ip + 4];
Con::printf("%i: OP_CALLFUNC name=%s nspace=%s callType=%s", ip - 1, fnName, fnNamespace, StringTableEntry callTypeName;
callType == FuncCallExprNode::FunctionCall ? "FunctionCall" switch (callType)
: callType == FuncCallExprNode::MethodCall ? "MethodCall" : "ParentCall"); {
case FuncCallExprNode::FunctionCall: callTypeName = "FunctionCall"; break;
case FuncCallExprNode::MethodCall: callTypeName = "MethodCall"; break;
case FuncCallExprNode::ParentCall: callTypeName = "ParentCall"; break;
case FuncCallExprNode::StaticCall: callTypeName = "StaticCall"; break;
}
Con::printf("%i: OP_CALLFUNC name=%s nspace=%s callType=%s", ip - 1, fnName, fnNamespace, callTypeName);
ip += 5; ip += 5;
break; break;
} }
case OP_CALLFUNC_POINTER:
{
Con::printf("%i: OP_CALLFUNC_POINTER", ip - 1);
break;
}
case OP_CALLFUNC_THIS:
{
StringTableEntry fnName = CodeToSTE(code, ip);
Con::printf("%i: OP_CALLFUNC_THIS name=%s ", ip - 1, fnName);
ip += 2;
break;
}
case OP_ADVANCE_STR: case OP_ADVANCE_STR:
{ {
Con::printf("%i: OP_ADVANCE_STR", ip - 1); Con::printf("%i: OP_ADVANCE_STR", ip - 1);
@ -1434,22 +1369,10 @@ void CodeBlock::dumpInstructions(U32 startIp, bool upToReturn)
break; break;
} }
case OP_PUSH_VAR:
{
Con::printf("%i: OP_PUSH_VAR", ip - 1);
break;
}
case OP_PUSH_THIS:
{
Con::printf("%i: OP_PUSH_THIS varName=%s", ip - 1, CodeToSTE(code, ip));
ip += 2;
break;
}
case OP_PUSH_FRAME: case OP_PUSH_FRAME:
{ {
Con::printf("%i: OP_PUSH_FRAME", ip - 1); Con::printf("%i: OP_PUSH_FRAME count=%i", ip - 1, code[ip]);
++ip;
break; break;
} }

File diff suppressed because it is too large Load diff

View file

@ -1,262 +0,0 @@
//-----------------------------------------------------------------------------
// Copyright (c) 2012 GarageGames, LLC
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------
#ifndef _CODEINTERPRETER_H_
#define _CODEINTERPRETER_H_
#include "console/codeBlock.h"
#include "console/console.h"
#include "console/consoleInternal.h"
/// Frame data for a foreach/foreach$ loop.
struct IterStackRecord
{
/// If true, this is a foreach$ loop; if not, it's a foreach loop.
bool mIsStringIter;
/// The iterator variable.
Dictionary::Entry* mVariable;
/// Information for an object iterator loop.
struct ObjectPos
{
/// The set being iterated over.
SimSet* mSet;
/// Current index in the set.
U32 mIndex;
};
/// Information for a string iterator loop.
struct StringPos
{
/// The raw string data on the string stack.
StringStackPtr mString;
/// Current parsing position.
U32 mIndex;
};
union
{
ObjectPos mObj;
StringPos mStr;
} mData;
};
enum OPCodeReturn
{
exitCode = -1,
success = 0,
breakContinue = 1
};
class CodeInterpreter
{
public:
CodeInterpreter(CodeBlock *cb);
~CodeInterpreter();
ConsoleValueRef exec(U32 ip,
StringTableEntry functionName,
Namespace *thisNamespace,
U32 argc,
ConsoleValueRef *argv,
bool noCalls,
StringTableEntry packageName,
S32 setFrame);
static void init();
// Methods
private:
void parseArgs(U32 &ip);
/// Group op codes
/// @{
OPCodeReturn op_func_decl(U32 &ip);
OPCodeReturn op_create_object(U32 &ip);
OPCodeReturn op_add_object(U32 &ip);
OPCodeReturn op_end_object(U32 &ip);
OPCodeReturn op_finish_object(U32 &ip);
OPCodeReturn op_jmpiffnot(U32 &ip);
OPCodeReturn op_jmpifnot(U32 &ip);
OPCodeReturn op_jmpiff(U32 &ip);
OPCodeReturn op_jmpif(U32 &ip);
OPCodeReturn op_jmpifnot_np(U32 &ip);
OPCodeReturn op_jmpif_np(U32 &ip);
OPCodeReturn op_jmp(U32 &ip);
OPCodeReturn op_return_void(U32 &ip);
OPCodeReturn op_return(U32 &ip);
OPCodeReturn op_return_flt(U32 &ip);
OPCodeReturn op_return_uint(U32 &ip);
OPCodeReturn op_cmpeq(U32 &ip);
OPCodeReturn op_cmpgr(U32 &ip);
OPCodeReturn op_cmpge(U32 &ip);
OPCodeReturn op_cmplt(U32 &ip);
OPCodeReturn op_cmple(U32 &ip);
OPCodeReturn op_cmpne(U32 &ip);
OPCodeReturn op_xor(U32 &ip);
OPCodeReturn op_mod(U32 &ip);
OPCodeReturn op_bitand(U32 &ip);
OPCodeReturn op_bitor(U32 &ip);
OPCodeReturn op_not(U32 &ip);
OPCodeReturn op_notf(U32 &ip);
OPCodeReturn op_onescomplement(U32 &ip);
OPCodeReturn op_shr(U32 &ip);
OPCodeReturn op_shl(U32 &ip);
OPCodeReturn op_and(U32 &ip);
OPCodeReturn op_or(U32 &ip);
OPCodeReturn op_add(U32 &ip);
OPCodeReturn op_sub(U32 &ip);
OPCodeReturn op_mul(U32 &ip);
OPCodeReturn op_div(U32 &ip);
OPCodeReturn op_neg(U32 &ip);
OPCodeReturn op_inc(U32 &ip);
OPCodeReturn op_dec(U32 &ip);
OPCodeReturn op_setcurvar(U32 &ip);
OPCodeReturn op_setcurvar_create(U32 &ip);
OPCodeReturn op_setcurvar_array(U32 &ip);
OPCodeReturn op_setcurvar_array_varlookup(U32 &ip);
OPCodeReturn op_setcurvar_array_create(U32 &ip);
OPCodeReturn op_setcurvar_array_create_varlookup(U32 &ip);
OPCodeReturn op_loadvar_uint(U32 &ip);
OPCodeReturn op_loadvar_flt(U32 &ip);
OPCodeReturn op_loadvar_str(U32 &ip);
OPCodeReturn op_loadvar_var(U32 &ip);
OPCodeReturn op_savevar_uint(U32 &ip);
OPCodeReturn op_savevar_flt(U32 &ip);
OPCodeReturn op_savevar_str(U32 &ip);
OPCodeReturn op_savevar_var(U32 &ip);
OPCodeReturn op_setcurobject(U32 &ip);
OPCodeReturn op_setcurobject_internal(U32 &ip);
OPCodeReturn op_setcurobject_new(U32 &ip);
OPCodeReturn op_setcurfield(U32 &ip);
OPCodeReturn op_setcurfield_array(U32 &ip);
OPCodeReturn op_setcurfield_type(U32 &ip);
OPCodeReturn op_setcurfield_this(U32 &ip);
OPCodeReturn op_setcurfield_array_var(U32 &ip);
OPCodeReturn op_loadfield_uint(U32 &ip);
OPCodeReturn op_loadfield_flt(U32 &ip);
OPCodeReturn op_loadfield_str(U32 &ip);
OPCodeReturn op_savefield_uint(U32 &ip);
OPCodeReturn op_savefield_flt(U32 &ip);
OPCodeReturn op_savefield_str(U32 &ip);
OPCodeReturn op_str_to_uint(U32 &ip);
OPCodeReturn op_str_to_flt(U32 &ip);
OPCodeReturn op_str_to_none(U32 &ip);
OPCodeReturn op_flt_to_uint(U32 &ip);
OPCodeReturn op_flt_to_str(U32 &ip);
OPCodeReturn op_flt_to_none(U32 &ip);
OPCodeReturn op_uint_to_flt(U32 &ip);
OPCodeReturn op_uint_to_str(U32 &ip);
OPCodeReturn op_uint_to_none(U32 &ip);
OPCodeReturn op_copyvar_to_none(U32 &ip);
OPCodeReturn op_loadimmed_uint(U32 &ip);
OPCodeReturn op_loadimmed_flt(U32 &ip);
OPCodeReturn op_tag_to_str(U32 &ip);
OPCodeReturn op_loadimmed_str(U32 &ip);
OPCodeReturn op_docblock_str(U32 &ip);
OPCodeReturn op_loadimmed_ident(U32 &ip);
OPCodeReturn op_callfunc_resolve(U32 &ip);
OPCodeReturn op_callfunc(U32 &ip);
OPCodeReturn op_callfunc_pointer(U32 &ip);
OPCodeReturn op_callfunc_this(U32 &ip);
OPCodeReturn op_advance_str(U32 &ip);
OPCodeReturn op_advance_str_appendchar(U32 &ip);
OPCodeReturn op_advance_str_comma(U32 &ip);
OPCodeReturn op_advance_str_nul(U32 &ip);
OPCodeReturn op_rewind_str(U32 &ip);
OPCodeReturn op_terminate_rewind_str(U32 &ip);
OPCodeReturn op_compare_str(U32 &ip);
OPCodeReturn op_push(U32 &ip);
OPCodeReturn op_push_uint(U32 &ip);
OPCodeReturn op_push_flt(U32 &ip);
OPCodeReturn op_push_var(U32 &ip);
OPCodeReturn op_push_this(U32 &ip);
OPCodeReturn op_push_frame(U32 &ip);
OPCodeReturn op_assert(U32 &ip);
OPCodeReturn op_break(U32 &ip);
OPCodeReturn op_iter_begin_str(U32 &ip);
OPCodeReturn op_iter_begin(U32 &ip);
OPCodeReturn op_iter(U32 &ip);
OPCodeReturn op_iter_end(U32 &ip);
OPCodeReturn op_invalid(U32 &ip);
/// @}
private:
CodeBlock *mCodeBlock;
/// Group exec arguments.
struct
{
StringTableEntry functionName;
Namespace *thisNamespace;
U32 argc;
ConsoleValueRef *argv;
bool noCalls;
StringTableEntry packageName;
S32 setFrame;
} mExec;
U32 mIterDepth;
F64 *mCurFloatTable;
char *mCurStringTable;
StringTableEntry mThisFunctionName;
bool mPopFrame;
// Add local object creation stack [7/9/2007 Black]
static const U32 objectCreationStackSize = 32;
U32 mObjectCreationStackIndex;
struct
{
SimObject *newObject;
U32 failJump;
} mObjectCreationStack[objectCreationStackSize];
SimObject *mCurrentNewObject;
U32 mFailJump;
StringTableEntry mPrevField;
StringTableEntry mCurField;
SimObject *mPrevObject;
SimObject *mCurObject;
SimObject *mSaveObject;
SimObject *mThisObject;
Namespace::Entry *mNSEntry;
StringTableEntry mCurFNDocBlock;
StringTableEntry mCurNSDocBlock;
U32 mCallArgc;
ConsoleValueRef *mCallArgv;
CodeBlock *mSaveCodeBlock;
// note: anything returned is pushed to CSTK and will be invalidated on the next exec()
ConsoleValueRef mReturnValue;
U32 mCurrentInstruction;
static const S32 nsDocLength = 128;
char mNSDocBlockClass[nsDocLength];
};
#endif

File diff suppressed because it is too large Load diff

View file

@ -93,26 +93,28 @@ namespace Compiler
OP_MUL, OP_MUL,
OP_DIV, OP_DIV,
OP_NEG, OP_NEG,
OP_INC, OP_INC,
OP_DEC,
OP_SETCURVAR, OP_SETCURVAR,
OP_SETCURVAR_CREATE, OP_SETCURVAR_CREATE,
OP_SETCURVAR_ARRAY, OP_SETCURVAR_ARRAY,
OP_SETCURVAR_ARRAY_VARLOOKUP,
OP_SETCURVAR_ARRAY_CREATE, OP_SETCURVAR_ARRAY_CREATE,
OP_SETCURVAR_ARRAY_CREATE_VARLOOKUP,
OP_LOADVAR_UINT,// 40 OP_LOADVAR_UINT,// 40
OP_LOADVAR_FLT, OP_LOADVAR_FLT,
OP_LOADVAR_STR, OP_LOADVAR_STR,
OP_LOADVAR_VAR,
OP_SAVEVAR_UINT, OP_SAVEVAR_UINT,
OP_SAVEVAR_FLT, OP_SAVEVAR_FLT,
OP_SAVEVAR_STR, OP_SAVEVAR_STR,
OP_SAVEVAR_VAR,
OP_LOAD_LOCAL_VAR_UINT,
OP_LOAD_LOCAL_VAR_FLT,
OP_LOAD_LOCAL_VAR_STR,
OP_SAVE_LOCAL_VAR_UINT,
OP_SAVE_LOCAL_VAR_FLT,
OP_SAVE_LOCAL_VAR_STR,
OP_SETCUROBJECT, OP_SETCUROBJECT,
OP_SETCUROBJECT_NEW, OP_SETCUROBJECT_NEW,
@ -121,8 +123,6 @@ namespace Compiler
OP_SETCURFIELD, OP_SETCURFIELD,
OP_SETCURFIELD_ARRAY, // 50 OP_SETCURFIELD_ARRAY, // 50
OP_SETCURFIELD_TYPE, OP_SETCURFIELD_TYPE,
OP_SETCURFIELD_ARRAY_VAR,
OP_SETCURFIELD_THIS,
OP_LOADFIELD_UINT, OP_LOADFIELD_UINT,
OP_LOADFIELD_FLT, OP_LOADFIELD_FLT,
@ -141,19 +141,15 @@ namespace Compiler
OP_UINT_TO_FLT, OP_UINT_TO_FLT,
OP_UINT_TO_STR, OP_UINT_TO_STR,
OP_UINT_TO_NONE, OP_UINT_TO_NONE,
OP_COPYVAR_TO_NONE,
OP_LOADIMMED_UINT, OP_LOADIMMED_UINT,
OP_LOADIMMED_FLT, OP_LOADIMMED_FLT,
OP_TAG_TO_STR, OP_TAG_TO_STR,
OP_LOADIMMED_STR, // 70 OP_LOADIMMED_STR, // 70
OP_DOCBLOCK_STR, OP_DOCBLOCK_STR, // 76
OP_LOADIMMED_IDENT, OP_LOADIMMED_IDENT,
OP_CALLFUNC_RESOLVE,
OP_CALLFUNC, OP_CALLFUNC,
OP_CALLFUNC_POINTER,
OP_CALLFUNC_THIS,
OP_ADVANCE_STR, OP_ADVANCE_STR,
OP_ADVANCE_STR_APPENDCHAR, OP_ADVANCE_STR_APPENDCHAR,
@ -166,8 +162,6 @@ namespace Compiler
OP_PUSH, // String OP_PUSH, // String
OP_PUSH_UINT, // Integer OP_PUSH_UINT, // Integer
OP_PUSH_FLT, // Float OP_PUSH_FLT, // Float
OP_PUSH_VAR, // Variable
OP_PUSH_THIS, // This pointer
OP_PUSH_FRAME, // Frame OP_PUSH_FRAME, // Frame
OP_ASSERT, OP_ASSERT,

View file

@ -271,8 +271,6 @@ StringTableEntry gCurrentFile;
StringTableEntry gCurrentRoot; StringTableEntry gCurrentRoot;
/// @} /// @}
S32 gObjectCopyFailures = -1;
bool alwaysUseDebugOutput = true; bool alwaysUseDebugOutput = true;
bool useTimestamp = false; bool useTimestamp = false;
bool useRealTimestamp = false; bool useRealTimestamp = false;
@ -327,6 +325,7 @@ void init()
// Setup the console types. // Setup the console types.
ConsoleBaseType::initialize(); ConsoleBaseType::initialize();
ConsoleValue::init();
// And finally, the ACR... // And finally, the ACR...
AbstractClassRep::initialize(); AbstractClassRep::initialize();
@ -344,10 +343,6 @@ void init()
addVariable( "instantGroup", TypeRealString, &gInstantGroup, "The group that objects will be added to when they are created.\n" addVariable( "instantGroup", TypeRealString, &gInstantGroup, "The group that objects will be added to when they are created.\n"
"@ingroup Console\n"); "@ingroup Console\n");
addVariable("Con::objectCopyFailures", TypeS32, &gObjectCopyFailures, "If greater than zero then it counts the number of object creation "
"failures based on a missing copy object and does not report an error..\n"
"@ingroup Console\n");
// Current script file name and root // Current script file name and root
addVariable( "Con::File", TypeString, &gCurrentFile, "The currently executing script file.\n" addVariable( "Con::File", TypeString, &gCurrentFile, "The currently executing script file.\n"
"@ingroup FileSystem\n"); "@ingroup FileSystem\n");
@ -1590,11 +1585,9 @@ ConsoleValueRef _internalExecute(SimObject *object, S32 argc, ConsoleValueRef ar
ICallMethod *com = dynamic_cast<ICallMethod *>(object); ICallMethod *com = dynamic_cast<ICallMethod *>(object);
if(com) if(com)
{ {
STR.pushFrame(); gCallStack.pushFrame(0);
CSTK.pushFrame();
com->callMethodArgList(argc, argv, false); com->callMethodArgList(argc, argv, false);
STR.popFrame(); gCallStack.popFrame();
CSTK.popFrame();
} }
} }
@ -2523,70 +2516,20 @@ DefineEngineFunction( logWarning, void, ( const char* message ),,
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
extern ConsoleValueStack CSTK; ConsoleValueToStringArrayWrapper::ConsoleValueToStringArrayWrapper(int targc, ConsoleValue *targv)
ConsoleValueRef::ConsoleValueRef(const ConsoleValueRef &ref)
{
value = ref.value;
}
ConsoleValueRef& ConsoleValueRef::operator=(const ConsoleValueRef &newValue)
{
value = newValue.value;
return *this;
}
ConsoleValueRef& ConsoleValueRef::operator=(const char *newValue)
{
AssertFatal(value, "value should not be NULL");
value->setStringValue(newValue);
return *this;
}
ConsoleValueRef& ConsoleValueRef::operator=(S32 newValue)
{
AssertFatal(value, "value should not be NULL");
value->setIntValue(newValue);
return *this;
}
ConsoleValueRef& ConsoleValueRef::operator=(U32 newValue)
{
AssertFatal(value, "value should not be NULL");
value->setIntValue(newValue);
return *this;
}
ConsoleValueRef& ConsoleValueRef::operator=(F32 newValue)
{
AssertFatal(value, "value should not be NULL");
value->setFloatValue(newValue);
return *this;
}
ConsoleValueRef& ConsoleValueRef::operator=(F64 newValue)
{
AssertFatal(value, "value should not be NULL");
value->setFloatValue(newValue);
return *this;
}
//------------------------------------------------------------------------------
StringStackWrapper::StringStackWrapper(int targc, ConsoleValueRef targv[])
{ {
argv = new const char*[targc]; argv = new const char*[targc];
argc = targc; argc = targc;
for (int i=0; i<targc; i++) for (S32 i = 0; i < targc; i++)
{ {
argv[i] = dStrdup(targv[i]); argv[i] = dStrdup(targv[i].getString());
} }
} }
StringStackWrapper::~StringStackWrapper() ConsoleValueToStringArrayWrapper::~ConsoleValueToStringArrayWrapper()
{ {
for (int i=0; i<argc; i++) for (S32 i = 0; i< argc; i++)
{ {
dFree(argv[i]); dFree(argv[i]);
} }
@ -2594,164 +2537,20 @@ StringStackWrapper::~StringStackWrapper()
} }
StringStackConsoleWrapper::StringStackConsoleWrapper(int targc, const char** targ) StringArrayToConsoleValueWrapper::StringArrayToConsoleValueWrapper(int targc, const char** targv)
{ {
argv = new ConsoleValueRef[targc]; argv = new ConsoleValue[targc];
argvValue = new ConsoleValue[targc];
argc = targc; argc = targc;
for (int i=0; i<targc; i++) { for (int i=0; i<targc; i++)
argvValue[i].init(); {
argv[i].value = &argvValue[i]; argv[i].setString(targv[i], dStrlen(targv[i]));
argvValue[i].setStackStringValue(targ[i]);
} }
} }
StringStackConsoleWrapper::~StringStackConsoleWrapper() StringArrayToConsoleValueWrapper::~StringArrayToConsoleValueWrapper()
{ {
for (int i=0; i<argc; i++)
{
argv[i] = 0;
}
delete[] argv; delete[] argv;
delete[] argvValue;
}
//------------------------------------------------------------------------------
S32 ConsoleValue::getSignedIntValue()
{
if(type <= TypeInternalString)
return (S32)fval;
else
return dAtoi(Con::getData(type, dataPtr, 0, enumTable));
}
U32 ConsoleValue::getIntValue()
{
if(type <= TypeInternalString)
return ival;
else
return dAtoi(Con::getData(type, dataPtr, 0, enumTable));
}
F32 ConsoleValue::getFloatValue()
{
if(type <= TypeInternalString)
return fval;
else
return dAtof(Con::getData(type, dataPtr, 0, enumTable));
}
const char *ConsoleValue::getStringValue()
{
if(type == TypeInternalString || type == TypeInternalStackString)
return sval;
else if (type == TypeInternalStringStackPtr)
return STR.mBuffer + (uintptr_t)sval;
else
{
// We need a string representation, so lets create one
const char *internalValue = NULL;
if(type == TypeInternalFloat)
internalValue = Con::getData(TypeF32, &fval, 0);
else if(type == TypeInternalInt)
internalValue = Con::getData(TypeS32, &ival, 0);
else
return Con::getData(type, dataPtr, 0, enumTable); // We can't save sval here since it is the same as dataPtr
if (!internalValue)
return "";
U32 stringLen = dStrlen(internalValue);
U32 newLen = ((stringLen + 1) + 15) & ~15; // pad upto next cache line
if (bufferLen == 0)
sval = (char *) dMalloc(newLen);
else if(newLen > bufferLen)
sval = (char *) dRealloc(sval, newLen);
dStrcpy(sval, internalValue, newLen);
bufferLen = newLen;
return sval;
}
}
StringStackPtr ConsoleValue::getStringStackPtr()
{
if (type == TypeInternalStringStackPtr)
return (uintptr_t)sval;
else
return (uintptr_t)-1;
}
bool ConsoleValue::getBoolValue()
{
if(type == TypeInternalString || type == TypeInternalStackString || type == TypeInternalStringStackPtr)
return dAtob(getStringValue());
if(type == TypeInternalFloat)
return fval > 0;
else if(type == TypeInternalInt)
return ival > 0;
else {
const char *value = Con::getData(type, dataPtr, 0, enumTable);
return dAtob(value);
}
}
void ConsoleValue::setIntValue(S32 val)
{
setFloatValue(val);
}
void ConsoleValue::setIntValue(U32 val)
{
if(type <= TypeInternalString)
{
fval = (F32)val;
ival = val;
if(bufferLen > 0)
{
dFree(sval);
bufferLen = 0;
}
sval = typeValueEmpty;
type = TypeInternalInt;
}
else
{
const char *dptr = Con::getData(TypeS32, &val, 0);
Con::setData(type, dataPtr, 0, 1, &dptr, enumTable);
}
}
void ConsoleValue::setBoolValue(bool val)
{
return setIntValue(val ? 1 : 0);
}
void ConsoleValue::setFloatValue(F32 val)
{
if(type <= TypeInternalString)
{
fval = val;
ival = static_cast<U32>(val);
if(bufferLen > 0)
{
dFree(sval);
bufferLen = 0;
}
sval = typeValueEmpty;
type = TypeInternalFloat;
}
else
{
const char *dptr = Con::getData(TypeF32, &val, 0);
Con::setData(type, dataPtr, 0, 1, &dptr, enumTable);
}
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------

View file

@ -183,13 +183,13 @@ void Dictionary::exportVariables(const char *varString, const char *fileName, bo
for (s = sortList.begin(); s != sortList.end(); s++) for (s = sortList.begin(); s != sortList.end(); s++)
{ {
switch ((*s)->value.type) switch ((*s)->value.getType())
{ {
case ConsoleValue::TypeInternalInt: case ConsoleValueType::cvInteger:
dSprintf(buffer, sizeof(buffer), "%s = %d;%s", (*s)->name, (*s)->value.ival, cat); dSprintf(buffer, sizeof(buffer), "%s = %d;%s", (*s)->name, (*s)->value.getInt(), cat);
break; break;
case ConsoleValue::TypeInternalFloat: case ConsoleValueType::cvFloat:
dSprintf(buffer, sizeof(buffer), "%s = %g;%s", (*s)->name, (*s)->value.fval, cat); dSprintf(buffer, sizeof(buffer), "%s = %g;%s", (*s)->name, (*s)->value.getFloat(), cat);
break; break;
default: default:
expandEscape(expandBuffer, (*s)->getStringValue()); expandEscape(expandBuffer, (*s)->getStringValue());
@ -243,13 +243,11 @@ void Dictionary::exportVariables(const char *varString, Vector<String> *names, V
if (values) if (values)
{ {
switch ((*s)->value.type) switch ((*s)->value.getType())
{ {
case ConsoleValue::TypeInternalInt: case ConsoleValueType::cvInteger:
values->push_back(String::ToString((*s)->value.ival)); case ConsoleValueType::cvFloat:
break; values->push_back(String((*s)->value.getString()));
case ConsoleValue::TypeInternalFloat:
values->push_back(String::ToString((*s)->value.fval));
break; break;
default: default:
expandEscape(expandBuffer, (*s)->getStringValue()); expandEscape(expandBuffer, (*s)->getStringValue());
@ -470,7 +468,6 @@ char *typeValueEmpty = "";
Dictionary::Entry::Entry(StringTableEntry in_name) Dictionary::Entry::Entry(StringTableEntry in_name)
{ {
name = in_name; name = in_name;
value.type = ConsoleValue::TypeInternalString;
notify = NULL; notify = NULL;
nextEntry = NULL; nextEntry = NULL;
mUsage = NULL; mUsage = NULL;
@ -508,150 +505,6 @@ const char *Dictionary::getVariable(StringTableEntry name, bool *entValid)
return ""; return "";
} }
void ConsoleValue::setStringValue(const char * value)
{
if (value == NULL) value = typeValueEmpty;
if (type <= ConsoleValue::TypeInternalString)
{
// Let's not remove empty-string-valued global vars from the dict.
// If we remove them, then they won't be exported, and sometimes
// it could be necessary to export such a global. There are very
// few empty-string global vars so there's no performance-related
// need to remove them from the dict.
/*
if(!value[0] && name[0] == '$')
{
gEvalState.globalVars.remove(this);
return;
}
*/
if (value == typeValueEmpty)
{
if (bufferLen > 0)
{
dFree(sval);
bufferLen = 0;
}
sval = typeValueEmpty;
fval = 0.f;
ival = 0;
type = TypeInternalString;
return;
}
U32 stringLen = dStrlen(value);
// If it's longer than 256 bytes, it's certainly not a number.
//
// (This decision may come back to haunt you. Shame on you if it
// does.)
if (stringLen < 256)
{
fval = dAtof(value);
ival = dAtoi(value);
}
else
{
fval = 0.f;
ival = 0;
}
// may as well pad to the next cache line
U32 newLen = ((stringLen + 1) + 15) & ~15;
if (bufferLen == 0)
sval = (char *)dMalloc(newLen);
else if (newLen > bufferLen)
sval = (char *)dRealloc(sval, newLen);
type = TypeInternalString;
bufferLen = newLen;
dStrcpy(sval, value, newLen);
}
else
Con::setData(type, dataPtr, 0, 1, &value, enumTable);
}
void ConsoleValue::setStackStringValue(const char *value)
{
if (value == NULL) value = typeValueEmpty;
if (type <= ConsoleValue::TypeInternalString)
{
// sval might still be temporarily present so we need to check and free it
if (bufferLen > 0)
{
dFree(sval);
bufferLen = 0;
}
if (value == typeValueEmpty)
{
sval = typeValueEmpty;
fval = 0.f;
ival = 0;
type = TypeInternalString;
return;
}
U32 stringLen = dStrlen(value);
if (stringLen < 256)
{
fval = dAtof(value);
ival = dAtoi(value);
}
else
{
fval = 0.f;
ival = 0;
}
type = TypeInternalStackString;
sval = (char*)value;
bufferLen = 0;
}
else
Con::setData(type, dataPtr, 0, 1, &value, enumTable);
}
void ConsoleValue::setStringStackPtrValue(StringStackPtr ptrValue)
{
if (type <= ConsoleValue::TypeInternalString)
{
const char *value = StringStackPtrRef(ptrValue).getPtr(&STR);
if (bufferLen > 0)
{
dFree(sval);
bufferLen = 0;
}
U32 stringLen = dStrlen(value);
if (stringLen < 256)
{
fval = dAtof(value);
ival = dAtoi(value);
}
else
{
fval = 0.f;
ival = 0;
}
type = TypeInternalStringStackPtr;
sval = (char*)(value - STR.mBuffer);
bufferLen = 0;
}
else
{
const char *value = StringStackPtrRef(ptrValue).getPtr(&STR);
Con::setData(type, dataPtr, 0, 1, &value, enumTable);
}
}
S32 Dictionary::getIntVariable(StringTableEntry name, bool *entValid) S32 Dictionary::getIntVariable(StringTableEntry name, bool *entValid)
{ {
Entry *ent = lookup(name); Entry *ent = lookup(name);

View file

@ -324,17 +324,17 @@ public:
inline U32 getIntValue() inline U32 getIntValue()
{ {
return value.getIntValue(); return value.getInt();
} }
inline F32 getFloatValue() inline F32 getFloatValue()
{ {
return value.getFloatValue(); return value.getFloat();
} }
inline const char *getStringValue() inline const char *getStringValue()
{ {
return value.getStringValue(); return value.getString();
} }
void setIntValue(U32 val) void setIntValue(U32 val)
@ -345,7 +345,7 @@ public:
return; return;
} }
value.setIntValue(val); value.setInt(val);
// Fire off the notification if we have one. // Fire off the notification if we have one.
if (notify) if (notify)
@ -360,23 +360,7 @@ public:
return; return;
} }
value.setFloatValue(val); value.setFloat(val);
// Fire off the notification if we have one.
if (notify)
notify->trigger();
}
void setStringStackPtrValue(StringStackPtr newValue)
{
if (mIsConstant)
{
Con::errorf("Cannot assign value to constant '%s'.", name);
return;
}
value.setStringStackPtrValue(newValue);
// Fire off the notification if we have one. // Fire off the notification if we have one.
if (notify) if (notify)
@ -391,8 +375,7 @@ public:
return; return;
} }
value.setStringValue(newValue); value.setString(newValue, dStrlen(newValue));
// Fire off the notification if we have one. // Fire off the notification if we have one.
if (notify) if (notify)
@ -471,6 +454,18 @@ public:
void validate(); void validate();
}; };
struct ConsoleValueFrame
{
ConsoleValue* values;
bool isReference;
ConsoleValueFrame(ConsoleValue* vals, bool isRef)
{
values = vals;
isReference = isRef;
}
};
class ExprEvalState class ExprEvalState
{ {
public: public:
@ -499,6 +494,9 @@ public:
/// an interior pointer that will become invalid when the object changes address. /// an interior pointer that will become invalid when the object changes address.
Vector< Dictionary* > stack; Vector< Dictionary* > stack;
Vector< ConsoleValueFrame > localStack;
ConsoleValueFrame* currentRegisterArray; // contains array at to top of localStack
/// ///
Dictionary globalVars; Dictionary globalVars;
@ -511,10 +509,43 @@ public:
void setIntVariable(S32 val); void setIntVariable(S32 val);
void setFloatVariable(F64 val); void setFloatVariable(F64 val);
void setStringVariable(const char *str); void setStringVariable(const char *str);
void setStringStackPtrVariable(StringStackPtr str);
void setCopyVariable();
void pushFrame(StringTableEntry frameName, Namespace *ns); TORQUE_FORCEINLINE S32 getLocalIntVariable(S32 reg)
{
return currentRegisterArray->values[reg].getInt();
}
TORQUE_FORCEINLINE F64 getLocalFloatVariable(S32 reg)
{
return currentRegisterArray->values[reg].getFloat();
}
TORQUE_FORCEINLINE const char* getLocalStringVariable(S32 reg)
{
return currentRegisterArray->values[reg].getString();
}
TORQUE_FORCEINLINE void setLocalIntVariable(S32 reg, S64 val)
{
currentRegisterArray->values[reg].setInt(val);
}
TORQUE_FORCEINLINE void setLocalFloatVariable(S32 reg, F64 val)
{
currentRegisterArray->values[reg].setFloat(val);
}
TORQUE_FORCEINLINE void setLocalStringVariable(S32 reg, const char* val, S32 len)
{
currentRegisterArray->values[reg].setString(val, len);
}
TORQUE_FORCEINLINE void setLocalStringTableEntryVariable(S32 reg, StringTableEntry val)
{
currentRegisterArray->values[reg].setStringTableEntry(val);
}
void pushFrame(StringTableEntry frameName, Namespace *ns, S32 regCount);
void popFrame(); void popFrame();
/// Puts a reference to an existing stack frame /// Puts a reference to an existing stack frame

View file

@ -79,7 +79,7 @@ void ConsoleLogger::initPersistFields()
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
bool ConsoleLogger::processArguments( S32 argc, ConsoleValueRef *argv ) bool ConsoleLogger::processArguments( S32 argc, ConsoleValue *argv )
{ {
if( argc == 0 ) if( argc == 0 )
return false; return false;
@ -87,10 +87,10 @@ bool ConsoleLogger::processArguments( S32 argc, ConsoleValueRef *argv )
bool append = false; bool append = false;
if (argc == 2) if (argc == 2)
append = dAtob( argv[1] ); append = argv[1].getBool();
mAppend = append; mAppend = append;
mFilename = StringTable->insert( argv[0] ); mFilename = StringTable->insert( argv[0].getString() );
if( init() ) if( init() )
{ {

View file

@ -81,7 +81,7 @@ class ConsoleLogger : public SimObject
/// // Example script constructor usage. /// // Example script constructor usage.
/// %obj = new ConsoleLogger( objName, logFileName, [append = false] ); /// %obj = new ConsoleLogger( objName, logFileName, [append = false] );
/// @endcode /// @endcode
bool processArguments( S32 argc, ConsoleValueRef *argv ); bool processArguments( S32 argc, ConsoleValue *argv );
/// Default constructor, make sure to initalize /// Default constructor, make sure to initalize
ConsoleLogger(); ConsoleLogger();

View file

@ -0,0 +1,121 @@
//-----------------------------------------------------------------------------
// Copyright (c) 2013 GarageGames, LLC
// Copyright (c) 2021 TGEMIT Authors & Contributors
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------
#ifndef _CONSOLE_CONSOLE_VALUE_STACK_H_
#define _CONSOLE_CONSOLE_VALUE_STACK_H_
template<S32 StackSize>
class ConsoleValueStack
{
constexpr static S32 allocatorSize = sizeof(ConsoleValue) * StackSize;
struct Frame
{
ConsoleValue* values;
S32 count;
S32 internalCounter;
};
Vector<Frame> stack;
char* memory;
S32 sp;
TORQUE_FORCEINLINE Frame alloc(S32 count)
{
AssertFatal(sp + count * sizeof(ConsoleValue) < allocatorSize, "ConsoleValueStack overflow");
ConsoleValue* ret = reinterpret_cast<ConsoleValue*>(memory + sp);
sp += count * sizeof(ConsoleValue);
return { ret, count, 1 };
}
TORQUE_FORCEINLINE void deAlloc(S32 count)
{
sp -= count * sizeof(ConsoleValue);
AssertFatal(sp >= 0, "Popped ConsoleValueStack too far, underflow");
}
public:
ConsoleValueStack()
{
memory = (char*)dMalloc(allocatorSize);
for (S32 i = 0; i < allocatorSize; i += sizeof(ConsoleValue))
{
constructInPlace<ConsoleValue>(reinterpret_cast<ConsoleValue*>(memory + i));
}
sp = 0;
}
~ConsoleValueStack()
{
dFree(memory);
}
TORQUE_FORCEINLINE void pushFrame(S32 count)
{
AssertISV(count >= 0, "Must be >= 0 when pushing stack frame");
// +1 for function name in argv[0]
const Frame& frame = alloc(count + 1);
stack.push_back(frame);
}
TORQUE_FORCEINLINE void popFrame()
{
AssertISV(stack.size() > 0, "Stack Underflow");
deAlloc(stack.last().count);
stack.pop_back();
}
TORQUE_FORCEINLINE void pushInt(S64 value)
{
Frame& frame = stack.last();
frame.values[frame.internalCounter++].setInt(value);
}
TORQUE_FORCEINLINE void pushFloat(F64 value)
{
Frame& frame = stack.last();
frame.values[frame.internalCounter++].setFloat(value);
}
TORQUE_FORCEINLINE void pushString(const char* value, S32 len)
{
Frame& frame = stack.last();
frame.values[frame.internalCounter++].setString(value, len);
}
TORQUE_FORCEINLINE void argvc(StringTableEntry fn, S32& argc, ConsoleValue** argv)
{
Frame& frame = stack.last();
argc = frame.count;
// First param is always function name
frame.values[0].setStringTableEntry(fn);
*argv = frame.values;
}
};
#endif

View file

@ -125,15 +125,12 @@ namespace Sim
SimDataBlockGroup *getDataBlockGroup(); SimDataBlockGroup *getDataBlockGroup();
SimGroup* getRootGroup(); SimGroup* getRootGroup();
SimObject* findObject(ConsoleValueRef&);
SimObject* findObject(SimObjectId); SimObject* findObject(SimObjectId);
SimObject* findObject(const ConsoleValue&);
SimObject* findObject(ConsoleValue*);
SimObject* findObject(const char* name); SimObject* findObject(const char* name);
SimObject* findObject(const char* fileName, S32 declarationLine); SimObject* findObject(const char* fileName, S32 declarationLine);
template<class T> inline bool findObject(ConsoleValueRef &ref,T*&t)
{
t = dynamic_cast<T*>(findObject(ref));
return t != NULL;
}
template<class T> inline bool findObject(SimObjectId iD,T*&t) template<class T> inline bool findObject(SimObjectId iD,T*&t)
{ {
t = dynamic_cast<T*>(findObject(iD)); t = dynamic_cast<T*>(findObject(iD));

View file

@ -328,11 +328,6 @@ SimObject* findObject(const char* fileName, S32 declarationLine)
return gRootGroup->findObjectByLineNumber(fileName, declarationLine, true); return gRootGroup->findObjectByLineNumber(fileName, declarationLine, true);
} }
SimObject* findObject(ConsoleValueRef &ref)
{
return findObject((const char*)ref);
}
SimObject* findObject(const char* name) SimObject* findObject(const char* name)
{ {
PROFILE_SCOPE(SimFindObject); PROFILE_SCOPE(SimFindObject);
@ -391,6 +386,24 @@ SimObject* findObject(const char* name)
return obj->findObject(name + len + 1); return obj->findObject(name + len + 1);
} }
SimObject* findObject(const ConsoleValue &val)
{
if (val.getType() == ConsoleValueType::cvNone)
return NULL;
if (val.getType() == ConsoleValueType::cvInteger)
return findObject((SimObjectId)val.getInt());
return findObject(val.getString());
}
SimObject* findObject(ConsoleValue* val)
{
if (val->getType() == ConsoleValueType::cvNone)
return NULL;
if (val->getType() == ConsoleValueType::cvInteger)
return findObject((SimObjectId)val->getInt());
return findObject(val->getString());
}
SimObject* findObject(SimObjectId id) SimObject* findObject(SimObjectId id)
{ {
return gIdDictionary->find(id); return gIdDictionary->find(id);

View file

@ -229,11 +229,16 @@ void SimSet::scriptSort( const String &scriptCallbackFn )
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void SimSet::callOnChildren( const String &method, S32 argc, ConsoleValueRef argv[], bool executeOnChildGroups ) void SimSet::callOnChildren( const String &method, S32 argc, ConsoleValue argv[], bool executeOnChildGroups )
{ {
// TODO(JTH): Implement
AssertISV(false, "TODO Implement");
return;
/*
// Prep the arguments for the console exec... // Prep the arguments for the console exec...
// Make sure and leave args[1] empty. // Make sure and leave args[1] empty.
ConsoleValueRef args[21] = { }; ConsoleValue args[21] = { };
ConsoleValue name_method; ConsoleValue name_method;
name_method.setStackStringValue(method.c_str()); name_method.setStackStringValue(method.c_str());
args[0] = ConsoleValueRef::fromValue(&name_method); args[0] = ConsoleValueRef::fromValue(&name_method);
@ -255,6 +260,7 @@ void SimSet::callOnChildren( const String &method, S32 argc, ConsoleValueRef arg
childSet->callOnChildren( method, argc, argv, executeOnChildGroups ); childSet->callOnChildren( method, argc, argv, executeOnChildGroups );
} }
} }
*/
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -838,7 +844,7 @@ SimGroup* SimGroup::deepClone()
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
bool SimGroup::processArguments(S32, ConsoleValueRef *argv) bool SimGroup::processArguments(S32, ConsoleValue *argv)
{ {
return true; return true;
} }

View file

@ -218,7 +218,7 @@ class SimSet : public SimObject, public TamlChildren
/// @} /// @}
void callOnChildren( const String &method, S32 argc, ConsoleValueRef argv[], bool executeOnChildGroups = true ); void callOnChildren( const String &method, S32 argc, ConsoleValue argv[], bool executeOnChildGroups = true );
/// Return the number of objects in this set as well as all sets that are contained /// Return the number of objects in this set as well as all sets that are contained
/// in this set and its children. /// in this set and its children.
@ -464,7 +464,7 @@ class SimGroup: public SimSet
virtual SimObject* findObject(const char* name); virtual SimObject* findObject(const char* name);
virtual void onRemove(); virtual void onRemove();
virtual bool processArguments( S32 argc, ConsoleValueRef *argv ); virtual bool processArguments( S32 argc, ConsoleValue *argv );
virtual SimObject* getObject(const S32& index); virtual SimObject* getObject(const S32& index);

View file

@ -207,228 +207,3 @@ void StringStack::clearFrames()
mStartStackSize = 0; mStartStackSize = 0;
mFunctionOffset = 0; mFunctionOffset = 0;
} }
void ConsoleValueStack::getArgcArgv(StringTableEntry name, U32 *argc, ConsoleValueRef **in_argv, bool popStackFrame /* = false */)
{
U32 startStack = mStackFrames[mFrame-1];
U32 argCount = getMin(mStackPos - startStack, (U32)MaxArgs - 1);
*in_argv = mArgv;
mArgv[0].value = CSTK.pushStackString(name);
for(U32 i = 0; i < argCount; i++) {
ConsoleValueRef *ref = &mArgv[i+1];
ref->value = &mStack[startStack + i];
}
argCount++;
*argc = argCount;
if(popStackFrame)
popFrame();
}
ConsoleValueStack::ConsoleValueStack() :
mFrame(0),
mStackPos(0)
{
for (int i=0; i<ConsoleValueStack::MaxStackDepth; i++) {
mStack[i].init();
mStack[i].type = ConsoleValue::TypeInternalString;
}
dMemset(mStackFrames, 0, sizeof(mStackFrames));
}
ConsoleValueStack::~ConsoleValueStack()
{
}
void ConsoleValueStack::pushVar(ConsoleValue *variable)
{
if (mStackPos == ConsoleValueStack::MaxStackDepth) {
AssertFatal(false, "Console Value Stack is empty");
return;
}
switch (variable->type)
{
case ConsoleValue::TypeInternalInt:
mStack[mStackPos++].setIntValue((S32)variable->getIntValue());
case ConsoleValue::TypeInternalFloat:
mStack[mStackPos++].setFloatValue((F32)variable->getFloatValue());
default:
mStack[mStackPos++].setStackStringValue(variable->getStringValue());
}
}
void ConsoleValueStack::pushValue(ConsoleValue &variable)
{
if (mStackPos == ConsoleValueStack::MaxStackDepth) {
AssertFatal(false, "Console Value Stack is empty");
return;
}
switch (variable.type)
{
case ConsoleValue::TypeInternalInt:
mStack[mStackPos++].setIntValue((S32)variable.getIntValue());
case ConsoleValue::TypeInternalFloat:
mStack[mStackPos++].setFloatValue((F32)variable.getFloatValue());
case ConsoleValue::TypeInternalStringStackPtr:
mStack[mStackPos++].setStringStackPtrValue(variable.getStringStackPtr());
default:
mStack[mStackPos++].setStringValue(variable.getStringValue());
}
}
ConsoleValue* ConsoleValueStack::reserveValues(U32 count)
{
U32 startPos = mStackPos;
if (startPos+count >= ConsoleValueStack::MaxStackDepth) {
AssertFatal(false, "Console Value Stack is empty");
return NULL;
}
//Con::printf("[%i]CSTK reserveValues %i", mStackPos, count);
mStackPos += count;
return &mStack[startPos];
}
bool ConsoleValueStack::reserveValues(U32 count, ConsoleValueRef *outValues)
{
U32 startPos = mStackPos;
if (startPos+count >= ConsoleValueStack::MaxStackDepth) {
AssertFatal(false, "Console Value Stack is empty");
return false;
}
//Con::printf("[%i]CSTK reserveValues %i", mStackPos, count);
for (U32 i=0; i<count; i++)
{
outValues[i].value = &mStack[mStackPos+i];
}
mStackPos += count;
return true;
}
ConsoleValue *ConsoleValueStack::pushString(const char *value)
{
if (mStackPos == ConsoleValueStack::MaxStackDepth) {
AssertFatal(false, "Console Value Stack is empty");
return NULL;
}
//Con::printf("[%i]CSTK pushString %s", mStackPos, value);
mStack[mStackPos++].setStringValue(value);
return &mStack[mStackPos-1];
}
ConsoleValue *ConsoleValueStack::pushStackString(const char *value)
{
if (mStackPos == ConsoleValueStack::MaxStackDepth) {
AssertFatal(false, "Console Value Stack is empty");
return NULL;
}
//Con::printf("[%i]CSTK pushString %s", mStackPos, value);
mStack[mStackPos++].setStackStringValue(value);
return &mStack[mStackPos-1];
}
ConsoleValue *ConsoleValueStack::pushStringStackPtr(StringStackPtr value)
{
if (mStackPos == ConsoleValueStack::MaxStackDepth) {
AssertFatal(false, "Console Value Stack is empty");
return NULL;
}
//Con::printf("[%i]CSTK pushStringStackPtr %s", mStackPos, StringStackPtrRef(value).getPtr(&STR));
mStack[mStackPos++].setStringStackPtrValue(value);
return &mStack[mStackPos-1];
}
ConsoleValue *ConsoleValueStack::pushUINT(U32 value)
{
if (mStackPos == ConsoleValueStack::MaxStackDepth) {
AssertFatal(false, "Console Value Stack is empty");
return NULL;
}
//Con::printf("[%i]CSTK pushUINT %i", mStackPos, value);
mStack[mStackPos++].setIntValue(value);
return &mStack[mStackPos-1];
}
ConsoleValue *ConsoleValueStack::pushFLT(float value)
{
if (mStackPos == ConsoleValueStack::MaxStackDepth) {
AssertFatal(false, "Console Value Stack is empty");
return NULL;
}
//Con::printf("[%i]CSTK pushFLT %f", mStackPos, value);
mStack[mStackPos++].setFloatValue(value);
return &mStack[mStackPos-1];
}
static ConsoleValue gNothing;
ConsoleValue* ConsoleValueStack::pop()
{
if (mStackPos == 0) {
AssertFatal(false, "Console Value Stack is empty");
return &gNothing;
}
return &mStack[--mStackPos];
}
void ConsoleValueStack::pushFrame()
{
//Con::printf("CSTK pushFrame[%i] (%i)", mFrame, mStackPos);
mStackFrames[mFrame++] = mStackPos;
}
void ConsoleValueStack::resetFrame()
{
if (mFrame == 0) {
mStackPos = 0;
return;
}
U32 start = mStackFrames[mFrame-1];
//for (U32 i=start; i<mStackPos; i++) {
//mStack[i].clear();
//}
mStackPos = start;
//Con::printf("CSTK resetFrame to %i", mStackPos);
}
void ConsoleValueStack::clearFrames()
{
mStackPos = 0;
mFrame = 0;
}
void ConsoleValueStack::popFrame()
{
//Con::printf("CSTK popFrame");
if (mFrame == 0) {
// Go back to start
mStackPos = 0;
return;
}
U32 start = mStackFrames[mFrame-1];
//for (U32 i=start; i<mStackPos; i++) {
//mStack[i].clear();
//}
mStackPos = start;
mFrame--;
}

View file

@ -189,51 +189,7 @@ struct StringStack
void getArgcArgv(StringTableEntry name, U32 *argc, const char ***in_argv, bool popStackFrame = false); void getArgcArgv(StringTableEntry name, U32 *argc, const char ***in_argv, bool popStackFrame = false);
}; };
// New console value stack
class ConsoleValueStack
{
enum {
MaxStackDepth = 1024,
MaxArgs = 20,
ReturnBufferSpace = 512
};
public:
ConsoleValueStack();
~ConsoleValueStack();
void pushVar(ConsoleValue *variable);
void pushValue(ConsoleValue &value);
ConsoleValue* reserveValues(U32 numValues);
bool reserveValues(U32 numValues, ConsoleValueRef *values);
ConsoleValue* pop();
ConsoleValue *pushString(const char *value);
ConsoleValue *pushStackString(const char *value);
ConsoleValue *pushStringStackPtr(StringStackPtr ptr);
ConsoleValue *pushUINT(U32 value);
ConsoleValue *pushFLT(float value);
void pushFrame();
void popFrame();
void resetFrame();
void clearFrames();
void getArgcArgv(StringTableEntry name, U32 *argc, ConsoleValueRef **in_argv, bool popStackFrame = false);
ConsoleValue mStack[MaxStackDepth];
U32 mStackFrames[MaxStackDepth];
U32 mFrame;
U32 mStackPos;
ConsoleValueRef mArgv[MaxArgs];
};
extern StringStack STR; extern StringStack STR;
extern ConsoleValueStack CSTK;
inline char* StringStackPtrRef::getPtr(StringStack *stk) { return stk->mBuffer + mOffset; } inline char* StringStackPtrRef::getPtr(StringStack *stk) { return stk->mBuffer + mOffset; }

View file

@ -20,6 +20,7 @@
// IN THE SOFTWARE. // IN THE SOFTWARE.
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
#ifdef 0
#ifdef TORQUE_TESTS_ENABLED #ifdef TORQUE_TESTS_ENABLED
#include "testing/unitTesting.h" #include "testing/unitTesting.h"
#include "platform/platform.h" #include "platform/platform.h"
@ -393,3 +394,4 @@ TEST(Script, Basic_Package)
} }
#endif #endif
#endif

View file

@ -1,3 +1,5 @@
#ifdef 0
#ifdef TORQUE_TESTS_ENABLED #ifdef TORQUE_TESTS_ENABLED
#include "testing/unitTesting.h" #include "testing/unitTesting.h"
#include "platform/platform.h" #include "platform/platform.h"
@ -253,3 +255,4 @@ TEST(Con, execute)
} }
#endif #endif
#endif

View file

@ -1,3 +1,4 @@
#if 0
#ifdef TORQUE_TESTS_ENABLED #ifdef TORQUE_TESTS_ENABLED
#include "testing/unitTesting.h" #include "testing/unitTesting.h"
#include "platform/platform.h" #include "platform/platform.h"
@ -148,3 +149,4 @@ TEST(EngineAPI, _EngineConsoleExecCallbackHelper)
} }
#endif #endif
#endif

View file

@ -200,6 +200,11 @@ inline F64 dAtod(const char *str)
return strtod(str, NULL); return strtod(str, NULL);
} }
inline S64 dAtol(const char* str)
{
return strtol(str, NULL, 10);
}
inline char dToupper(const char c) inline char dToupper(const char c)
{ {
return toupper( c ); return toupper( c );

View file

@ -411,7 +411,7 @@ void WaterObject::inspectPostApply()
setMaskBits( UpdateMask | WaveMask | TextureMask | SoundMask ); setMaskBits( UpdateMask | WaveMask | TextureMask | SoundMask );
} }
bool WaterObject::processArguments( S32 argc, ConsoleValueRef *argv ) bool WaterObject::processArguments( S32 argc, ConsoleValue *argv )
{ {
if( typeid( *this ) == typeid( WaterObject ) ) if( typeid( *this ) == typeid( WaterObject ) )
{ {

View file

@ -156,7 +156,7 @@ public:
virtual bool onAdd(); virtual bool onAdd();
virtual void onRemove(); virtual void onRemove();
virtual void inspectPostApply(); virtual void inspectPostApply();
virtual bool processArguments(S32 argc, ConsoleValueRef *argv); virtual bool processArguments(S32 argc, ConsoleValue *argv);
// NetObject // NetObject
virtual U32 packUpdate( NetConnection * conn, U32 mask, BitStream *stream ); virtual U32 packUpdate( NetConnection * conn, U32 mask, BitStream *stream );

View file

@ -319,7 +319,7 @@ void GuiControl::initPersistFields()
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
bool GuiControl::processArguments(S32 argc, ConsoleValueRef *argv) bool GuiControl::processArguments(S32 argc, ConsoleValue *argv)
{ {
// argv[0] - The GuiGroup to add this control to when it's created. // argv[0] - The GuiGroup to add this control to when it's created.
// this is an optional parameter that may be specified at // this is an optional parameter that may be specified at

View file

@ -341,7 +341,7 @@ class GuiControl : public SimGroup
GuiControl(); GuiControl();
virtual ~GuiControl(); virtual ~GuiControl();
virtual bool processArguments(S32 argc, ConsoleValueRef *argv); virtual bool processArguments(S32 argc, ConsoleValue *argv);
static void initPersistFields(); static void initPersistFields();
static void consoleInit(); static void consoleInit();

View file

@ -2858,17 +2858,17 @@ void WorldEditor::initPersistFields()
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// These methods are needed for the console interfaces. // These methods are needed for the console interfaces.
void WorldEditor::ignoreObjClass( U32 argc, ConsoleValueRef *argv ) void WorldEditor::ignoreObjClass( U32 argc, ConsoleValue *argv )
{ {
for(S32 i = 2; i < argc; i++) for(S32 i = 2; i < argc; i++)
{ {
ClassInfo::Entry * entry = getClassEntry(argv[i]); ClassInfo::Entry * entry = getClassEntry(argv[i].getString());
if(entry) if(entry)
entry->mIgnoreCollision = true; entry->mIgnoreCollision = true;
else else
{ {
entry = new ClassInfo::Entry; entry = new ClassInfo::Entry;
entry->mName = StringTable->insert(argv[i]); entry->mName = StringTable->insert(argv[i].getString());
entry->mIgnoreCollision = true; entry->mIgnoreCollision = true;
if(!addClassEntry(entry)) if(!addClassEntry(entry))
delete entry; delete entry;

View file

@ -76,7 +76,7 @@ class WorldEditor : public EditTSCtrl
Point3F p2; Point3F p2;
}; };
void ignoreObjClass(U32 argc, ConsoleValueRef* argv); void ignoreObjClass(U32 argc, ConsoleValue* argv);
void clearIgnoreList(); void clearIgnoreList();
static bool setObjectsUseBoxCenter( void *object, const char *index, const char *data ) { static_cast<WorldEditor*>(object)->setObjectsUseBoxCenter( dAtob( data ) ); return false; }; static bool setObjectsUseBoxCenter( void *object, const char *index, const char *data ) { static_cast<WorldEditor*>(object)->setObjectsUseBoxCenter( dAtob( data ) ); return false; };

View file

@ -55,31 +55,36 @@ DefineEngineStringlyVariadicFunction( mathInit, void, 1, 10, "( ... )"
} }
for (argc--, argv++; argc; argc--, argv++) for (argc--, argv++; argc; argc--, argv++)
{ {
if (dStricmp(*argv, "DETECT") == 0) { const char* str = (*argv).getString();
if (dStricmp(str, "DETECT") == 0) {
Math::init(0); Math::init(0);
return; return;
} }
if (dStricmp(*argv, "C") == 0) { if (dStricmp(str, "C") == 0) {
properties |= CPU_PROP_C; properties |= CPU_PROP_C;
continue; continue;
} }
if (dStricmp(*argv, "FPU") == 0) { if (dStricmp(str, "FPU") == 0) {
properties |= CPU_PROP_FPU; properties |= CPU_PROP_FPU;
continue; continue;
} }
if (dStricmp(*argv, "MMX") == 0) { if (dStricmp(str, "MMX") == 0) {
properties |= CPU_PROP_MMX; properties |= CPU_PROP_MMX;
continue; continue;
} }
if (dStricmp(*argv, "3DNOW") == 0) { if (dStricmp(str, "3DNOW") == 0) {
properties |= CPU_PROP_3DNOW; properties |= CPU_PROP_3DNOW;
continue; continue;
} }
if (dStricmp(*argv, "SSE") == 0) { if (dStricmp(str, "SSE") == 0) {
properties |= CPU_PROP_SSE; properties |= CPU_PROP_SSE;
continue; continue;
} }
Con::printf("Error: MathInit(): ignoring unknown math extension '%s'", argv->getStringValue()); if (dStricmp(str, "SSE2") == 0) {
properties |= CPU_PROP_SSE2;
continue;
}
Con::printf("Error: MathInit(): ignoring unknown math extension '%s'", str);
} }
Math::init(properties); Math::init(properties);
} }

View file

@ -316,7 +316,7 @@ void SFXSource::initPersistFields()
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
bool SFXSource::processArguments( S32 argc, ConsoleValueRef *argv ) bool SFXSource::processArguments( S32 argc, ConsoleValue *argv )
{ {
// Don't allow subclasses of this to be created via script. Force // Don't allow subclasses of this to be created via script. Force
// usage of the SFXSystem functions. // usage of the SFXSystem functions.

View file

@ -382,7 +382,7 @@ class SFXSource : public SimGroup
/// We overload this to disable creation of /// We overload this to disable creation of
/// a source via script 'new'. /// a source via script 'new'.
virtual bool processArguments( S32 argc, ConsoleValueRef *argv ); virtual bool processArguments( S32 argc, ConsoleValue *argv );
// Console getters/setters. // Console getters/setters.
static bool _setDescription( void *obj, const char *index, const char *data ); static bool _setDescription( void *obj, const char *index, const char *data );

View file

@ -95,7 +95,7 @@ void SFXTrack::initPersistFields()
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
bool SFXTrack::processArguments( S32 argc, ConsoleValueRef *argv ) bool SFXTrack::processArguments( S32 argc, ConsoleValue *argv )
{ {
if( typeid( *this ) == typeid( SFXTrack ) ) if( typeid( *this ) == typeid( SFXTrack ) )
{ {

View file

@ -61,7 +61,7 @@ class SFXTrack : public SimDataBlock
StringTableEntry mParameters[ MaxNumParameters ]; StringTableEntry mParameters[ MaxNumParameters ];
/// Overload this to disable direct instantiation of this class via script 'new'. /// Overload this to disable direct instantiation of this class via script 'new'.
virtual bool processArguments( S32 argc, ConsoleValueRef *argv ); virtual bool processArguments( S32 argc, ConsoleValue *argv );
public: public:

View file

@ -238,7 +238,7 @@ void CustomFeatureGLSL::addVertTexCoord(String name)
mVars.push_back(newVarHolder); mVars.push_back(newVarHolder);
} }
void CustomFeatureGLSL::writeLine(String format, S32 argc, ConsoleValueRef * argv) void CustomFeatureGLSL::writeLine(String format, S32 argc, ConsoleValue * argv)
{ {
//do the var/arg fetching here //do the var/arg fetching here
Vector<Var*> varList; Vector<Var*> varList;
@ -246,7 +246,7 @@ void CustomFeatureGLSL::writeLine(String format, S32 argc, ConsoleValueRef * arg
for (U32 i = 0; i < argc; i++) for (U32 i = 0; i < argc; i++)
{ {
String varName = argv[i].getStringValue(); String varName = argv[i].getString();
Var* newVar = (Var*)LangElement::find(varName.c_str()); Var* newVar = (Var*)LangElement::find(varName.c_str());
if (!newVar) if (!newVar)
{ {
@ -304,7 +304,7 @@ void CustomFeatureGLSL::writeLine(String format, S32 argc, ConsoleValueRef * arg
if (!newVar) if (!newVar)
{ {
//couldn't find that variable, bail out //couldn't find that variable, bail out
Con::errorf("CustomShaderFeature::writeLine: unable to find variable %s, meaning it was not declared before being used!", argv[i].getStringValue()); Con::errorf("CustomShaderFeature::writeLine: unable to find variable %s, meaning it was not declared before being used!", argv[i].getString());
return; return;
} }
} }

View file

@ -128,5 +128,5 @@ public:
void addTexture(String name, String type, String samplerState, U32 arraySize); void addTexture(String name, String type, String samplerState, U32 arraySize);
void addConnector(String name, String type, String elementName); void addConnector(String name, String type, String elementName);
void addVertTexCoord(String name); void addVertTexCoord(String name);
void writeLine(String format, S32 argc, ConsoleValueRef* argv); void writeLine(String format, S32 argc, ConsoleValue* argv);
}; };

View file

@ -385,7 +385,7 @@ void CustomFeatureHLSL::addVertTexCoord(String name)
mVars.push_back(newVarHolder); mVars.push_back(newVarHolder);
} }
void CustomFeatureHLSL::writeLine(String format, S32 argc, ConsoleValueRef * argv) void CustomFeatureHLSL::writeLine(String format, S32 argc, ConsoleValue *argv)
{ {
//do the var/arg fetching here //do the var/arg fetching here
Vector<Var*> varList; Vector<Var*> varList;
@ -393,7 +393,7 @@ void CustomFeatureHLSL::writeLine(String format, S32 argc, ConsoleValueRef * arg
for (U32 i = 0; i < argc; i++) for (U32 i = 0; i < argc; i++)
{ {
String varName = argv[i].getStringValue(); String varName = argv[i].getString();
Var* newVar = (Var*)LangElement::find(varName.c_str()); Var* newVar = (Var*)LangElement::find(varName.c_str());
if (!newVar) if (!newVar)
{ {
@ -451,7 +451,7 @@ void CustomFeatureHLSL::writeLine(String format, S32 argc, ConsoleValueRef * arg
if (!newVar) if (!newVar)
{ {
//couldn't find that variable, bail out //couldn't find that variable, bail out
Con::errorf("CustomShaderFeature::writeLine: unable to find variable %s, meaning it was not declared before being used!", argv[i].getStringValue()); Con::errorf("CustomShaderFeature::writeLine: unable to find variable %s, meaning it was not declared before being used!", argv[i].getString());
return; return;
} }
} }

View file

@ -128,5 +128,5 @@ public:
void addTexture(String name, String type, String samplerState, U32 arraySize); void addTexture(String name, String type, String samplerState, U32 arraySize);
void addConnector(String name, String type, String elementName); void addConnector(String name, String type, String elementName);
void addVertTexCoord(String name); void addVertTexCoord(String name);
void writeLine(String format, S32 argc, ConsoleValueRef* argv); void writeLine(String format, S32 argc, ConsoleValue* argv);
}; };

View file

@ -189,7 +189,7 @@ bool CustomShaderFeatureData::hasFeature(String name)
return false; return false;
} }
void CustomShaderFeatureData::writeLine(String format, S32 argc, ConsoleValueRef* argv) void CustomShaderFeatureData::writeLine(String format, S32 argc, ConsoleValue* argv)
{ {
#ifdef TORQUE_D3D11 #ifdef TORQUE_D3D11
if (GFX->getAdapterType() == GFXAdapterType::Direct3D11) if (GFX->getAdapterType() == GFXAdapterType::Direct3D11)

View file

@ -77,7 +77,7 @@ public:
void addVertTexCoord(String name); void addVertTexCoord(String name);
bool hasFeature(String name); bool hasFeature(String name);
void writeLine(String format, S32 argc, ConsoleValueRef *argv); void writeLine(String format, S32 argc, ConsoleValue *argv);
}; };
#endif #endif