2012-09-19 15:15:01 +00:00
//-----------------------------------------------------------------------------
// 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.
//-----------------------------------------------------------------------------
# include "platform/platform.h"
# include "console/console.h"
# include "console/telnetDebugger.h"
# include "console/ast.h"
# include "core/tAlgorithm.h"
# include "core/strings/findMatch.h"
# include "console/consoleInternal.h"
# include "core/stream/fileStream.h"
# include "console/compiler.h"
# include "console/simBase.h"
template < typename T >
struct Token
{
T value ;
S32 lineNumber ;
} ;
# include "console/cmdgram.h"
namespace Compiler
{
2021-03-30 23:33:19 +00:00
U32 compileBlock ( StmtNode * block , CodeStream & codeStream , U32 ip )
2012-09-19 15:15:01 +00:00
{
2021-03-30 23:33:19 +00:00
for ( StmtNode * walk = block ; walk ; walk = walk - > getNext ( ) )
2021-04-27 02:52:58 +00:00
{
2014-09-07 16:38:35 +00:00
ip = walk - > compileStmt ( codeStream , ip ) ;
2021-04-27 02:52:58 +00:00
}
2014-09-07 16:38:35 +00:00
return codeStream . tell ( ) ;
2012-09-19 15:15:01 +00:00
}
2021-03-30 23:33:19 +00:00
}
using namespace Compiler ;
2017-11-06 04:33:32 +00:00
2021-09-21 01:00:33 +00:00
FuncVars gEvalFuncVars ;
2021-03-30 23:33:19 +00:00
FuncVars * gFuncVars = NULL ;
2012-09-19 15:15:01 +00:00
2021-06-19 17:48:32 +00:00
inline FuncVars * getFuncVars ( S32 lineNumber )
2021-04-17 18:31:27 +00:00
{
2021-06-19 17:48:32 +00:00
AssertISV ( gFuncVars , avar ( " Attemping to use local variable in global scope. File: %s Line: %d " , CodeBlock : : smCurrentParser - > getCurrentFile ( ) , lineNumber ) ) ;
2021-04-17 18:31:27 +00:00
return gFuncVars ;
}
2012-09-19 15:15:01 +00:00
//-----------------------------------------------------------------------------
2021-03-30 23:33:19 +00:00
void StmtNode : : addBreakLine ( CodeStream & code )
2012-09-19 15:15:01 +00:00
{
2014-09-07 16:38:35 +00:00
code . addBreakLine ( dbgLineNumber , code . tell ( ) ) ;
2012-09-19 15:15:01 +00:00
}
//------------------------------------------------------------
2021-10-07 04:27:39 +00:00
StmtNode : : StmtNode ( ) : dbgLineNumber ( 0 )
2012-09-19 15:15:01 +00:00
{
2021-03-30 23:33:19 +00:00
next = NULL ;
2012-09-19 15:15:01 +00:00
dbgFileName = CodeBlock : : smCurrentParser - > getCurrentFile ( ) ;
}
void StmtNode : : setPackage ( StringTableEntry )
{
}
2021-10-07 04:27:39 +00:00
void StmtNode : : append ( StmtNode * appended )
2012-09-19 15:15:01 +00:00
{
2021-03-30 23:33:19 +00:00
StmtNode * walk = this ;
while ( walk - > next )
walk = walk - > next ;
2021-10-07 04:27:39 +00:00
walk - > next = appended ;
2012-09-19 15:15:01 +00:00
}
void FunctionDeclStmtNode : : setPackage ( StringTableEntry packageName )
{
package = packageName ;
}
//------------------------------------------------------------
//
// Console language compilers
//
//------------------------------------------------------------
2021-03-30 23:33:19 +00:00
U32 BreakStmtNode : : compileStmt ( CodeStream & codeStream , U32 ip )
2012-09-19 15:15:01 +00:00
{
2017-11-06 04:33:32 +00:00
if ( codeStream . inLoop ( ) )
2012-09-19 15:15:01 +00:00
{
2014-09-07 16:38:35 +00:00
addBreakLine ( codeStream ) ;
codeStream . emit ( OP_JMP ) ;
codeStream . emitFix ( CodeStream : : FIXTYPE_BREAK ) ;
2012-09-19 15:15:01 +00:00
}
2014-09-07 16:38:35 +00:00
else
2012-09-19 15:15:01 +00:00
{
2014-09-07 16:38:35 +00:00
Con : : warnf ( ConsoleLogEntry : : General , " %s (%d): break outside of loop... ignoring. " , dbgFileName , dbgLineNumber ) ;
2012-09-19 15:15:01 +00:00
}
2014-09-07 16:38:35 +00:00
return codeStream . tell ( ) ;
2012-09-19 15:15:01 +00:00
}
//------------------------------------------------------------
2021-03-30 23:33:19 +00:00
U32 ContinueStmtNode : : compileStmt ( CodeStream & codeStream , U32 ip )
2012-09-19 15:15:01 +00:00
{
2017-11-06 04:33:32 +00:00
if ( codeStream . inLoop ( ) )
2012-09-19 15:15:01 +00:00
{
2014-09-07 16:38:35 +00:00
addBreakLine ( codeStream ) ;
codeStream . emit ( OP_JMP ) ;
codeStream . emitFix ( CodeStream : : FIXTYPE_CONTINUE ) ;
2012-09-19 15:15:01 +00:00
}
2014-09-07 16:38:35 +00:00
else
2012-09-19 15:15:01 +00:00
{
2014-09-07 16:38:35 +00:00
Con : : warnf ( ConsoleLogEntry : : General , " %s (%d): continue outside of loop... ignoring. " , dbgFileName , dbgLineNumber ) ;
2012-09-19 15:15:01 +00:00
}
2014-09-07 16:38:35 +00:00
return codeStream . tell ( ) ;
2012-09-19 15:15:01 +00:00
}
//------------------------------------------------------------
2021-03-30 23:33:19 +00:00
U32 ExprNode : : compileStmt ( CodeStream & codeStream , U32 ip )
2012-09-19 15:15:01 +00:00
{
2014-09-07 16:38:35 +00:00
addBreakLine ( codeStream ) ;
2012-09-19 15:15:01 +00:00
return compile ( codeStream , ip , TypeReqNone ) ;
}
//------------------------------------------------------------
2021-03-30 23:33:19 +00:00
U32 ReturnStmtNode : : compileStmt ( CodeStream & codeStream , U32 ip )
2012-09-19 15:15:01 +00:00
{
2014-09-07 16:38:35 +00:00
addBreakLine ( codeStream ) ;
2017-11-06 04:33:32 +00:00
if ( ! expr )
2014-09-07 16:38:35 +00:00
codeStream . emit ( OP_RETURN_VOID ) ;
2012-09-19 15:15:01 +00:00
else
{
2014-10-27 21:55:17 +00:00
TypeReq walkType = expr - > getPreferredType ( ) ;
if ( walkType = = TypeReqNone ) walkType = TypeReqString ;
ip = expr - > compile ( codeStream , ip , walkType ) ;
// Return the correct type
switch ( walkType ) {
2021-03-30 23:33:19 +00:00
case TypeReqUInt :
codeStream . emit ( OP_RETURN_UINT ) ;
break ;
case TypeReqFloat :
codeStream . emit ( OP_RETURN_FLT ) ;
break ;
default :
codeStream . emit ( OP_RETURN ) ;
break ;
2014-10-27 21:55:17 +00:00
}
2012-09-19 15:15:01 +00:00
}
2014-09-07 16:38:35 +00:00
return codeStream . tell ( ) ;
2012-09-19 15:15:01 +00:00
}
//------------------------------------------------------------
2021-03-30 23:33:19 +00:00
ExprNode * IfStmtNode : : getSwitchOR ( ExprNode * left , ExprNode * list , bool string )
2012-09-19 15:15:01 +00:00
{
2021-03-30 23:33:19 +00:00
ExprNode * nextExpr = ( ExprNode * ) list - > getNext ( ) ;
ExprNode * test ;
2017-11-06 04:33:32 +00:00
if ( string )
test = StreqExprNode : : alloc ( left - > dbgLineNumber , left , list , true ) ;
2012-09-19 15:15:01 +00:00
else
2017-11-06 04:33:32 +00:00
test = IntBinaryExprNode : : alloc ( left - > dbgLineNumber , opEQ , left , list ) ;
if ( ! nextExpr )
2012-09-19 15:15:01 +00:00
return test ;
2017-11-06 04:33:32 +00:00
return IntBinaryExprNode : : alloc ( test - > dbgLineNumber , opOR , test , getSwitchOR ( left , nextExpr , string ) ) ;
2012-09-19 15:15:01 +00:00
}
2021-03-30 23:33:19 +00:00
void IfStmtNode : : propagateSwitchExpr ( ExprNode * left , bool string )
2012-09-19 15:15:01 +00:00
{
testExpr = getSwitchOR ( left , testExpr , string ) ;
2017-11-06 04:33:32 +00:00
if ( propagate & & elseBlock )
2021-03-30 23:33:19 +00:00
( ( IfStmtNode * ) elseBlock ) - > propagateSwitchExpr ( left , string ) ;
2012-09-19 15:15:01 +00:00
}
2021-03-30 23:33:19 +00:00
U32 IfStmtNode : : compileStmt ( CodeStream & codeStream , U32 ip )
2012-09-19 15:15:01 +00:00
{
2014-09-07 16:38:35 +00:00
U32 endifIp , elseIp ;
addBreakLine ( codeStream ) ;
2017-11-06 04:33:32 +00:00
if ( testExpr - > getPreferredType ( ) = = TypeReqUInt )
2012-09-19 15:15:01 +00:00
{
integer = true ;
}
else
{
integer = false ;
}
ip = testExpr - > compile ( codeStream , ip , integer ? TypeReqUInt : TypeReqFloat ) ;
2014-09-07 16:38:35 +00:00
codeStream . emit ( integer ? OP_JMPIFNOT : OP_JMPIFFNOT ) ;
2012-09-19 15:15:01 +00:00
2017-11-06 04:33:32 +00:00
if ( elseBlock )
2012-09-19 15:15:01 +00:00
{
2014-09-07 16:38:35 +00:00
elseIp = codeStream . emit ( 0 ) ;
elseOffset = compileBlock ( ifBlock , codeStream , ip ) + 2 ;
codeStream . emit ( OP_JMP ) ;
endifIp = codeStream . emit ( 0 ) ;
endifOffset = compileBlock ( elseBlock , codeStream , ip ) ;
2017-11-06 04:33:32 +00:00
2014-09-07 16:38:35 +00:00
codeStream . patch ( endifIp , endifOffset ) ;
codeStream . patch ( elseIp , elseOffset ) ;
2012-09-19 15:15:01 +00:00
}
else
{
2014-09-07 16:38:35 +00:00
endifIp = codeStream . emit ( 0 ) ;
endifOffset = compileBlock ( ifBlock , codeStream , ip ) ;
2017-11-06 04:33:32 +00:00
2014-09-07 16:38:35 +00:00
codeStream . patch ( endifIp , endifOffset ) ;
2012-09-19 15:15:01 +00:00
}
2017-11-06 04:33:32 +00:00
2014-09-07 16:38:35 +00:00
// Resolve fixes
return codeStream . tell ( ) ;
2012-09-19 15:15:01 +00:00
}
//------------------------------------------------------------
2021-03-30 23:33:19 +00:00
U32 LoopStmtNode : : compileStmt ( CodeStream & codeStream , U32 ip )
2012-09-19 15:15:01 +00:00
{
2017-11-06 04:33:32 +00:00
if ( testExpr - > getPreferredType ( ) = = TypeReqUInt )
2012-09-19 15:15:01 +00:00
{
integer = true ;
}
else
{
integer = false ;
}
2017-11-06 04:33:32 +00:00
2012-09-19 15:15:01 +00:00
// if it's a for loop or a while loop it goes:
// initExpr
// testExpr
// OP_JMPIFNOT to break point
// loopStartPoint:
// loopBlock
// continuePoint:
// endLoopExpr
// testExpr
// OP_JMPIF loopStartPoint
// breakPoint:
2017-11-06 04:33:32 +00:00
2012-09-19 15:15:01 +00:00
// otherwise if it's a do ... while() it goes:
// initExpr
// loopStartPoint:
// loopBlock
// continuePoint:
// endLoopExpr
// testExpr
// OP_JMPIF loopStartPoint
// breakPoint:
2017-11-06 04:33:32 +00:00
2014-09-07 16:38:35 +00:00
// loopBlockStart == start of loop block
// continue == skip to end
// break == exit loop
2017-11-06 04:33:32 +00:00
2014-09-07 16:38:35 +00:00
addBreakLine ( codeStream ) ;
codeStream . pushFixScope ( true ) ;
2017-11-06 04:33:32 +00:00
if ( initExpr )
2012-09-19 15:15:01 +00:00
ip = initExpr - > compile ( codeStream , ip , TypeReqNone ) ;
2017-11-06 04:33:32 +00:00
if ( ! isDoLoop )
2012-09-19 15:15:01 +00:00
{
ip = testExpr - > compile ( codeStream , ip , integer ? TypeReqUInt : TypeReqFloat ) ;
2014-09-07 16:38:35 +00:00
codeStream . emit ( integer ? OP_JMPIFNOT : OP_JMPIFFNOT ) ;
codeStream . emitFix ( CodeStream : : FIXTYPE_BREAK ) ;
2012-09-19 15:15:01 +00:00
}
// Compile internals of loop.
2014-09-07 16:38:35 +00:00
loopBlockStartOffset = codeStream . tell ( ) ;
continueOffset = compileBlock ( loopBlock , codeStream , ip ) ;
2012-09-19 15:15:01 +00:00
2017-11-06 04:33:32 +00:00
if ( endLoopExpr )
2012-09-19 15:15:01 +00:00
ip = endLoopExpr - > compile ( codeStream , ip , TypeReqNone ) ;
ip = testExpr - > compile ( codeStream , ip , integer ? TypeReqUInt : TypeReqFloat ) ;
2014-09-07 16:38:35 +00:00
codeStream . emit ( integer ? OP_JMPIF : OP_JMPIFF ) ;
codeStream . emitFix ( CodeStream : : FIXTYPE_LOOPBLOCKSTART ) ;
2017-11-06 04:33:32 +00:00
2014-09-07 16:38:35 +00:00
breakOffset = codeStream . tell ( ) ; // exit loop
2017-11-06 04:33:32 +00:00
2014-09-07 16:38:35 +00:00
codeStream . fixLoop ( loopBlockStartOffset , breakOffset , continueOffset ) ;
codeStream . popFixScope ( ) ;
2017-11-06 04:33:32 +00:00
2014-09-07 16:38:35 +00:00
return codeStream . tell ( ) ;
2012-09-19 15:15:01 +00:00
}
//------------------------------------------------------------
2021-03-30 23:33:19 +00:00
U32 IterStmtNode : : compileStmt ( CodeStream & codeStream , U32 ip )
2012-09-19 15:15:01 +00:00
{
// Instruction sequence:
//
// containerExpr
// OP_ITER_BEGIN varName .fail
// .continue:
// OP_ITER .break
// body
// OP_JMP .continue
// .break:
// OP_ITER_END
// .fail:
2017-11-06 04:33:32 +00:00
2014-09-07 16:38:35 +00:00
addBreakLine ( codeStream ) ;
2017-11-06 04:33:32 +00:00
2014-09-07 16:38:35 +00:00
codeStream . pushFixScope ( true ) ;
2017-11-06 04:33:32 +00:00
2021-04-04 04:50:37 +00:00
bool isGlobal = varName [ 0 ] = = ' $ ' ;
TypeReq varType = isStringIter ? TypeReqString : TypeReqUInt ;
2012-09-19 15:15:01 +00:00
const U32 startIp = ip ;
2021-08-20 02:25:11 +00:00
containerExpr - > compile ( codeStream , startIp , TypeReqString ) ;
2017-11-06 04:33:32 +00:00
2014-09-07 16:38:35 +00:00
codeStream . emit ( isStringIter ? OP_ITER_BEGIN_STR : OP_ITER_BEGIN ) ;
2021-04-04 04:50:37 +00:00
codeStream . emit ( isGlobal ) ;
if ( isGlobal )
codeStream . emitSTE ( varName ) ;
else
2021-06-19 17:48:32 +00:00
codeStream . emit ( getFuncVars ( dbgLineNumber ) - > assign ( varName , varType , dbgLineNumber ) ) ;
2014-09-07 16:38:35 +00:00
const U32 finalFix = codeStream . emit ( 0 ) ;
const U32 continueIp = codeStream . emit ( OP_ITER ) ;
codeStream . emitFix ( CodeStream : : FIXTYPE_BREAK ) ;
const U32 bodyIp = codeStream . tell ( ) ;
2017-11-06 04:33:32 +00:00
const U32 jmpIp = compileBlock ( body , codeStream , bodyIp ) ;
2012-09-19 15:15:01 +00:00
const U32 breakIp = jmpIp + 2 ;
const U32 finalIp = breakIp + 1 ;
2017-11-06 04:33:32 +00:00
2014-09-07 16:38:35 +00:00
codeStream . emit ( OP_JMP ) ;
codeStream . emitFix ( CodeStream : : FIXTYPE_CONTINUE ) ;
codeStream . emit ( OP_ITER_END ) ;
2017-11-06 04:33:32 +00:00
2014-09-07 16:38:35 +00:00
codeStream . patch ( finalFix , finalIp ) ;
codeStream . fixLoop ( bodyIp , breakIp , continueIp ) ;
codeStream . popFixScope ( ) ;
2017-11-06 04:33:32 +00:00
2014-09-07 16:38:35 +00:00
return codeStream . tell ( ) ;
2012-09-19 15:15:01 +00:00
}
//------------------------------------------------------------
2021-03-30 23:33:19 +00:00
U32 ConditionalExprNode : : compile ( CodeStream & codeStream , U32 ip , TypeReq type )
2012-09-19 15:15:01 +00:00
{
// code is testExpr
// JMPIFNOT falseStart
// trueExpr
// JMP end
// falseExpr
2017-11-06 04:33:32 +00:00
if ( testExpr - > getPreferredType ( ) = = TypeReqUInt )
2012-09-19 15:15:01 +00:00
{
integer = true ;
}
else
{
integer = false ;
}
2017-11-06 04:33:32 +00:00
2012-09-19 15:15:01 +00:00
ip = testExpr - > compile ( codeStream , ip , integer ? TypeReqUInt : TypeReqFloat ) ;
2014-09-07 16:38:35 +00:00
codeStream . emit ( integer ? OP_JMPIFNOT : OP_JMPIFFNOT ) ;
2017-11-06 04:33:32 +00:00
2014-09-07 16:38:35 +00:00
U32 jumpElseIp = codeStream . emit ( 0 ) ;
2012-09-19 15:15:01 +00:00
ip = trueExpr - > compile ( codeStream , ip , type ) ;
2014-09-07 16:38:35 +00:00
codeStream . emit ( OP_JMP ) ;
U32 jumpEndIp = codeStream . emit ( 0 ) ;
codeStream . patch ( jumpElseIp , codeStream . tell ( ) ) ;
2012-09-19 15:15:01 +00:00
ip = falseExpr - > compile ( codeStream , ip , type ) ;
2014-09-07 16:38:35 +00:00
codeStream . patch ( jumpEndIp , codeStream . tell ( ) ) ;
2017-11-06 04:33:32 +00:00
2014-09-07 16:38:35 +00:00
return codeStream . tell ( ) ;
2012-09-19 15:15:01 +00:00
}
TypeReq ConditionalExprNode : : getPreferredType ( )
{
return trueExpr - > getPreferredType ( ) ;
}
//------------------------------------------------------------
2021-03-30 23:33:19 +00:00
U32 FloatBinaryExprNode : : compile ( CodeStream & codeStream , U32 ip , TypeReq type )
2012-09-19 15:15:01 +00:00
{
2021-03-30 23:33:19 +00:00
if ( optimize ( ) )
{
ip = optimizedNode - > compile ( codeStream , ip , type ) ;
return codeStream . tell ( ) ;
}
2012-09-19 15:15:01 +00:00
ip = right - > compile ( codeStream , ip , TypeReqFloat ) ;
ip = left - > compile ( codeStream , ip , TypeReqFloat ) ;
U32 operand = OP_INVALID ;
2017-11-06 04:33:32 +00:00
switch ( op )
{
2021-03-30 23:33:19 +00:00
case ' + ' :
operand = OP_ADD ;
break ;
case ' - ' :
operand = OP_SUB ;
break ;
case ' / ' :
operand = OP_DIV ;
break ;
case ' * ' :
operand = OP_MUL ;
break ;
2012-09-19 15:15:01 +00:00
}
2014-09-07 16:38:35 +00:00
codeStream . emit ( operand ) ;
return codeStream . tell ( ) ;
2012-09-19 15:15:01 +00:00
}
TypeReq FloatBinaryExprNode : : getPreferredType ( )
{
return TypeReqFloat ;
}
//------------------------------------------------------------
void IntBinaryExprNode : : getSubTypeOperand ( )
{
subType = TypeReqUInt ;
2017-11-06 04:33:32 +00:00
switch ( op )
{
2021-03-30 23:33:19 +00:00
case ' ^ ' :
operand = OP_XOR ;
break ;
case ' % ' :
operand = OP_MOD ;
break ;
case ' & ' :
operand = OP_BITAND ;
break ;
case ' | ' :
operand = OP_BITOR ;
break ;
case ' < ' :
operand = OP_CMPLT ;
subType = TypeReqFloat ;
break ;
case ' > ' :
operand = OP_CMPGR ;
subType = TypeReqFloat ;
break ;
case opGE :
operand = OP_CMPGE ;
subType = TypeReqFloat ;
break ;
case opLE :
operand = OP_CMPLE ;
subType = TypeReqFloat ;
break ;
case opEQ :
operand = OP_CMPEQ ;
subType = TypeReqFloat ;
break ;
case opNE :
operand = OP_CMPNE ;
subType = TypeReqFloat ;
break ;
case opOR :
operand = OP_OR ;
break ;
case opAND :
operand = OP_AND ;
break ;
case opSHR :
operand = OP_SHR ;
break ;
case opSHL :
operand = OP_SHL ;
break ;
}
}
U32 IntBinaryExprNode : : compile ( CodeStream & codeStream , U32 ip , TypeReq type )
{
if ( optimize ( ) )
right = optimizedNode ;
2012-09-19 15:15:01 +00:00
getSubTypeOperand ( ) ;
2017-11-06 04:33:32 +00:00
if ( operand = = OP_OR | | operand = = OP_AND )
2012-09-19 15:15:01 +00:00
{
ip = left - > compile ( codeStream , ip , subType ) ;
2014-09-07 16:38:35 +00:00
codeStream . emit ( operand = = OP_OR ? OP_JMPIF_NP : OP_JMPIFNOT_NP ) ;
U32 jmpIp = codeStream . emit ( 0 ) ;
2012-09-19 15:15:01 +00:00
ip = right - > compile ( codeStream , ip , subType ) ;
2014-09-07 16:38:35 +00:00
codeStream . patch ( jmpIp , ip ) ;
2012-09-19 15:15:01 +00:00
}
else
{
ip = right - > compile ( codeStream , ip , subType ) ;
ip = left - > compile ( codeStream , ip , subType ) ;
2014-09-07 16:38:35 +00:00
codeStream . emit ( operand ) ;
2012-09-19 15:15:01 +00:00
}
2014-09-07 16:38:35 +00:00
return codeStream . tell ( ) ;
2012-09-19 15:15:01 +00:00
}
TypeReq IntBinaryExprNode : : getPreferredType ( )
{
return TypeReqUInt ;
}
//------------------------------------------------------------
2021-03-30 23:33:19 +00:00
U32 StreqExprNode : : compile ( CodeStream & codeStream , U32 ip , TypeReq type )
2012-09-19 15:15:01 +00:00
{
// eval str left
// OP_ADVANCE_STR_NUL
// eval str right
// OP_COMPARE_STR
// optional conversion
2017-11-06 04:33:32 +00:00
2012-09-19 15:15:01 +00:00
ip = left - > compile ( codeStream , ip , TypeReqString ) ;
ip = right - > compile ( codeStream , ip , TypeReqString ) ;
2014-09-07 16:38:35 +00:00
codeStream . emit ( OP_COMPARE_STR ) ;
2017-11-06 04:33:32 +00:00
if ( ! eq )
2014-09-07 16:38:35 +00:00
codeStream . emit ( OP_NOT ) ;
return codeStream . tell ( ) ;
2012-09-19 15:15:01 +00:00
}
TypeReq StreqExprNode : : getPreferredType ( )
{
return TypeReqUInt ;
}
//------------------------------------------------------------
2021-03-30 23:33:19 +00:00
U32 StrcatExprNode : : compile ( CodeStream & codeStream , U32 ip , TypeReq type )
2012-09-19 15:15:01 +00:00
{
ip = left - > compile ( codeStream , ip , TypeReqString ) ;
2021-04-27 02:52:58 +00:00
if ( appendChar )
2012-09-19 15:15:01 +00:00
{
2014-09-07 16:38:35 +00:00
codeStream . emit ( OP_ADVANCE_STR_APPENDCHAR ) ;
codeStream . emit ( appendChar ) ;
2012-09-19 15:15:01 +00:00
}
ip = right - > compile ( codeStream , ip , TypeReqString ) ;
2014-09-07 16:38:35 +00:00
codeStream . emit ( OP_REWIND_STR ) ;
return codeStream . tell ( ) ;
2012-09-19 15:15:01 +00:00
}
TypeReq StrcatExprNode : : getPreferredType ( )
{
return TypeReqString ;
}
//------------------------------------------------------------
2021-03-30 23:33:19 +00:00
U32 CommaCatExprNode : : compile ( CodeStream & codeStream , U32 ip , TypeReq type )
2012-09-19 15:15:01 +00:00
{
ip = left - > compile ( codeStream , ip , TypeReqString ) ;
2021-04-27 02:52:58 +00:00
codeStream . emit ( OP_ADVANCE_STR_APPENDCHAR ) ;
codeStream . emit ( ' _ ' ) ;
2012-09-19 15:15:01 +00:00
ip = right - > compile ( codeStream , ip , TypeReqString ) ;
2014-09-07 16:38:35 +00:00
codeStream . emit ( OP_REWIND_STR ) ;
2012-09-19 15:15:01 +00:00
// At this point the stack has the concatenated string.
// But we're paranoid, so accept (but whine) if we get an oddity...
2017-11-06 04:33:32 +00:00
if ( type = = TypeReqUInt | | type = = TypeReqFloat )
2012-09-19 15:15:01 +00:00
Con : : warnf ( ConsoleLogEntry : : General , " %s (%d): converting comma string to a number... probably wrong. " , dbgFileName , dbgLineNumber ) ;
2021-04-27 02:52:58 +00:00
2014-09-07 16:38:35 +00:00
return codeStream . tell ( ) ;
2012-09-19 15:15:01 +00:00
}
TypeReq CommaCatExprNode : : getPreferredType ( )
{
return TypeReqString ;
}
//------------------------------------------------------------
2021-03-30 23:33:19 +00:00
U32 IntUnaryExprNode : : compile ( CodeStream & codeStream , U32 ip , TypeReq type )
2012-09-19 15:15:01 +00:00
{
integer = true ;
TypeReq prefType = expr - > getPreferredType ( ) ;
2017-11-06 04:33:32 +00:00
if ( op = = ' ! ' & & ( prefType = = TypeReqFloat | | prefType = = TypeReqString ) )
2012-09-19 15:15:01 +00:00
integer = false ;
2017-11-06 04:33:32 +00:00
2012-09-19 15:15:01 +00:00
ip = expr - > compile ( codeStream , ip , integer ? TypeReqUInt : TypeReqFloat ) ;
2017-11-06 04:33:32 +00:00
if ( op = = ' ! ' )
2014-09-07 16:38:35 +00:00
codeStream . emit ( integer ? OP_NOT : OP_NOTF ) ;
2017-11-06 04:33:32 +00:00
else if ( op = = ' ~ ' )
2014-09-07 16:38:35 +00:00
codeStream . emit ( OP_ONESCOMPLEMENT ) ;
2021-04-27 02:52:58 +00:00
2014-09-07 16:38:35 +00:00
return codeStream . tell ( ) ;
2012-09-19 15:15:01 +00:00
}
TypeReq IntUnaryExprNode : : getPreferredType ( )
{
return TypeReqUInt ;
}
//------------------------------------------------------------
2021-03-30 23:33:19 +00:00
U32 FloatUnaryExprNode : : compile ( CodeStream & codeStream , U32 ip , TypeReq type )
2012-09-19 15:15:01 +00:00
{
ip = expr - > compile ( codeStream , ip , TypeReqFloat ) ;
2014-09-07 16:38:35 +00:00
codeStream . emit ( OP_NEG ) ;
2021-04-27 02:52:58 +00:00
2014-09-07 16:38:35 +00:00
return codeStream . tell ( ) ;
2012-09-19 15:15:01 +00:00
}
TypeReq FloatUnaryExprNode : : getPreferredType ( )
{
return TypeReqFloat ;
}
//------------------------------------------------------------
2021-03-30 23:33:19 +00:00
U32 VarNode : : compile ( CodeStream & codeStream , U32 ip , TypeReq type )
2012-09-19 15:15:01 +00:00
{
2021-03-30 23:33:19 +00:00
// if this has an arrayIndex...
// OP_LOADIMMED_IDENT
// varName
// OP_ADVANCE_STR
// evaluate arrayIndex TypeReqString
// OP_REWIND_STR
// OP_SETCURVAR_ARRAY
// OP_LOADVAR (type)
2017-11-06 04:33:32 +00:00
2012-09-19 15:15:01 +00:00
// else
// OP_SETCURVAR
// varName
// OP_LOADVAR (type)
2017-11-06 04:33:32 +00:00
if ( type = = TypeReqNone )
2014-09-07 16:38:35 +00:00
return codeStream . tell ( ) ;
2017-11-06 04:33:32 +00:00
2012-09-19 15:15:01 +00:00
precompileIdent ( varName ) ;
2021-03-30 23:33:19 +00:00
bool oldVariables = arrayIndex | | varName [ 0 ] = = ' $ ' ;
if ( oldVariables )
2012-09-19 15:15:01 +00:00
{
2021-03-30 23:33:19 +00:00
codeStream . emit ( arrayIndex ? OP_LOADIMMED_IDENT : OP_SETCURVAR ) ;
codeStream . emitSTE ( varName ) ;
if ( arrayIndex )
2017-11-06 04:33:32 +00:00
{
2021-04-27 02:52:58 +00:00
//codeStream.emit(OP_ADVANCE_STR);
2017-11-06 04:33:32 +00:00
ip = arrayIndex - > compile ( codeStream , ip , TypeReqString ) ;
codeStream . emit ( OP_REWIND_STR ) ;
codeStream . emit ( OP_SETCURVAR_ARRAY ) ;
2021-04-27 02:52:58 +00:00
codeStream . emit ( OP_POP_STK ) ;
2017-11-06 04:33:32 +00:00
}
2021-03-30 23:33:19 +00:00
switch ( type )
{
2017-11-06 04:33:32 +00:00
case TypeReqUInt :
codeStream . emit ( OP_LOADVAR_UINT ) ;
break ;
case TypeReqFloat :
codeStream . emit ( OP_LOADVAR_FLT ) ;
break ;
case TypeReqString :
codeStream . emit ( OP_LOADVAR_STR ) ;
break ;
case TypeReqNone :
break ;
default :
break ;
2021-03-30 23:33:19 +00:00
}
}
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 ) ;
}
2021-06-19 17:48:32 +00:00
codeStream . emit ( getFuncVars ( dbgLineNumber ) - > lookup ( varName , dbgLineNumber ) ) ;
2012-09-19 15:15:01 +00:00
}
2021-03-30 23:33:19 +00:00
2014-09-07 16:38:35 +00:00
return codeStream . tell ( ) ;
2012-09-19 15:15:01 +00:00
}
TypeReq VarNode : : getPreferredType ( )
{
2021-03-30 23:33:19 +00:00
bool oldVariables = arrayIndex | | varName [ 0 ] = = ' $ ' ;
2021-06-19 17:48:32 +00:00
return oldVariables ? TypeReqNone : getFuncVars ( dbgLineNumber ) - > lookupType ( varName , dbgLineNumber ) ;
2012-09-19 15:15:01 +00:00
}
//------------------------------------------------------------
2021-03-30 23:33:19 +00:00
U32 IntNode : : compile ( CodeStream & codeStream , U32 ip , TypeReq type )
2012-09-19 15:15:01 +00:00
{
2017-11-06 04:33:32 +00:00
if ( type = = TypeReqString )
2012-09-19 15:15:01 +00:00
index = getCurrentStringTable ( ) - > addIntString ( value ) ;
2017-11-06 04:33:32 +00:00
else if ( type = = TypeReqFloat )
2012-09-19 15:15:01 +00:00
index = getCurrentFloatTable ( ) - > add ( value ) ;
2017-11-06 04:33:32 +00:00
switch ( type )
{
2021-03-30 23:33:19 +00:00
case TypeReqUInt :
codeStream . emit ( OP_LOADIMMED_UINT ) ;
codeStream . emit ( value ) ;
break ;
case TypeReqString :
codeStream . emit ( OP_LOADIMMED_STR ) ;
codeStream . emit ( index ) ;
break ;
case TypeReqFloat :
codeStream . emit ( OP_LOADIMMED_FLT ) ;
codeStream . emit ( index ) ;
break ;
case TypeReqNone :
break ;
2012-09-19 15:15:01 +00:00
}
2014-09-07 16:38:35 +00:00
return codeStream . tell ( ) ;
2012-09-19 15:15:01 +00:00
}
TypeReq IntNode : : getPreferredType ( )
{
return TypeReqUInt ;
}
//------------------------------------------------------------
2021-03-30 23:33:19 +00:00
U32 FloatNode : : compile ( CodeStream & codeStream , U32 ip , TypeReq type )
2012-09-19 15:15:01 +00:00
{
2017-11-06 04:33:32 +00:00
if ( type = = TypeReqString )
2012-09-19 15:15:01 +00:00
index = getCurrentStringTable ( ) - > addFloatString ( value ) ;
2017-11-06 04:33:32 +00:00
else if ( type = = TypeReqFloat )
2012-09-19 15:15:01 +00:00
index = getCurrentFloatTable ( ) - > add ( value ) ;
2017-11-06 04:33:32 +00:00
switch ( type )
{
2021-03-30 23:33:19 +00:00
case TypeReqUInt :
codeStream . emit ( OP_LOADIMMED_UINT ) ;
codeStream . emit ( U32 ( value ) ) ;
break ;
case TypeReqString :
codeStream . emit ( OP_LOADIMMED_STR ) ;
codeStream . emit ( index ) ;
break ;
case TypeReqFloat :
codeStream . emit ( OP_LOADIMMED_FLT ) ;
codeStream . emit ( index ) ;
break ;
case TypeReqNone :
break ;
2012-09-19 15:15:01 +00:00
}
2014-09-07 16:38:35 +00:00
return codeStream . tell ( ) ;
2012-09-19 15:15:01 +00:00
}
TypeReq FloatNode : : getPreferredType ( )
{
return TypeReqFloat ;
}
//------------------------------------------------------------
2021-03-30 23:33:19 +00:00
U32 StrConstNode : : compile ( CodeStream & codeStream , U32 ip , TypeReq type )
2012-09-19 15:15:01 +00:00
{
// Early out for documentation block.
2017-11-06 04:33:32 +00:00
if ( doc )
2012-09-19 15:15:01 +00:00
{
index = getCurrentStringTable ( ) - > add ( str , true , tag ) ;
}
2017-11-06 04:33:32 +00:00
else if ( type = = TypeReqString )
2012-09-19 15:15:01 +00:00
{
index = getCurrentStringTable ( ) - > add ( str , true , tag ) ;
}
2014-09-07 16:38:35 +00:00
else if ( type ! = TypeReqNone )
2012-09-19 15:15:01 +00:00
{
2014-09-07 16:38:35 +00:00
fVal = consoleStringToNumber ( str , dbgFileName , dbgLineNumber ) ;
2017-11-06 04:33:32 +00:00
if ( type = = TypeReqFloat )
2014-09-07 16:38:35 +00:00
{
index = getCurrentFloatTable ( ) - > add ( fVal ) ;
}
2012-09-19 15:15:01 +00:00
}
2017-11-06 04:33:32 +00:00
2012-09-19 15:15:01 +00:00
// If this is a DOCBLOCK, then process w/ appropriate op...
2017-11-06 04:33:32 +00:00
if ( doc )
2012-09-19 15:15:01 +00:00
{
2014-09-07 16:38:35 +00:00
codeStream . emit ( OP_DOCBLOCK_STR ) ;
codeStream . emit ( index ) ;
2012-09-19 15:15:01 +00:00
return ip ;
}
// Otherwise, deal with it normally as a string literal case.
2017-11-06 04:33:32 +00:00
switch ( type )
2012-09-19 15:15:01 +00:00
{
2021-03-30 23:33:19 +00:00
case TypeReqString :
codeStream . emit ( tag ? OP_TAG_TO_STR : OP_LOADIMMED_STR ) ;
codeStream . emit ( index ) ;
break ;
case TypeReqUInt :
codeStream . emit ( OP_LOADIMMED_UINT ) ;
codeStream . emit ( U32 ( fVal ) ) ;
break ;
case TypeReqFloat :
codeStream . emit ( OP_LOADIMMED_FLT ) ;
codeStream . emit ( index ) ;
break ;
case TypeReqNone :
break ;
2012-09-19 15:15:01 +00:00
}
2014-09-07 16:38:35 +00:00
return codeStream . tell ( ) ;
2012-09-19 15:15:01 +00:00
}
TypeReq StrConstNode : : getPreferredType ( )
{
return TypeReqString ;
}
//------------------------------------------------------------
2021-03-30 23:33:19 +00:00
U32 ConstantNode : : compile ( CodeStream & codeStream , U32 ip , TypeReq type )
2012-09-19 15:15:01 +00:00
{
2017-11-06 04:33:32 +00:00
if ( type = = TypeReqString )
2012-09-19 15:15:01 +00:00
{
precompileIdent ( value ) ;
}
2014-09-07 16:38:35 +00:00
else if ( type ! = TypeReqNone )
{
fVal = consoleStringToNumber ( value , dbgFileName , dbgLineNumber ) ;
2017-11-06 04:33:32 +00:00
if ( type = = TypeReqFloat )
2014-09-07 16:38:35 +00:00
index = getCurrentFloatTable ( ) - > add ( fVal ) ;
}
2017-11-06 04:33:32 +00:00
switch ( type )
{
2021-03-30 23:33:19 +00:00
case TypeReqString :
codeStream . emit ( OP_LOADIMMED_IDENT ) ;
codeStream . emitSTE ( value ) ;
break ;
case TypeReqUInt :
codeStream . emit ( OP_LOADIMMED_UINT ) ;
codeStream . emit ( U32 ( fVal ) ) ;
break ;
case TypeReqFloat :
codeStream . emit ( OP_LOADIMMED_FLT ) ;
codeStream . emit ( index ) ;
break ;
case TypeReqNone :
break ;
2012-09-19 15:15:01 +00:00
}
return ip ;
}
TypeReq ConstantNode : : getPreferredType ( )
{
return TypeReqString ;
}
//------------------------------------------------------------
2021-03-30 23:33:19 +00:00
U32 AssignExprNode : : compile ( CodeStream & codeStream , U32 ip , TypeReq type )
2012-09-19 15:15:01 +00:00
{
subType = expr - > getPreferredType ( ) ;
2017-11-06 04:33:32 +00:00
if ( subType = = TypeReqNone )
2012-09-19 15:15:01 +00:00
subType = type ;
2017-11-06 04:33:32 +00:00
if ( subType = = TypeReqNone )
2021-03-30 23:33:19 +00:00
subType = TypeReqString ;
2017-11-06 04:33:32 +00:00
2021-03-30 23:33:19 +00:00
// if it's an array expr, the formula is:
2017-11-06 04:33:32 +00:00
// eval expr
// (push and pop if it's TypeReqString) OP_ADVANCE_STR
2021-03-30 23:33:19 +00:00
// OP_LOADIMMED_IDENT
// varName
// OP_ADVANCE_STR
// eval array
// OP_REWIND_STR
// OP_SETCURVAR_ARRAY_CREATE
2012-09-19 15:15:01 +00:00
// OP_TERMINATE_REWIND_STR
// OP_SAVEVAR
2017-11-06 04:33:32 +00:00
2012-09-19 15:15:01 +00:00
//else
// eval expr
// OP_SETCURVAR_CREATE
// varname
// OP_SAVEVAR
2017-11-06 04:33:32 +00:00
2021-03-30 23:33:19 +00:00
precompileIdent ( varName ) ;
2012-09-19 15:15:01 +00:00
ip = expr - > compile ( codeStream , ip , subType ) ;
2021-03-30 23:33:19 +00:00
bool oldVariables = arrayIndex | | varName [ 0 ] = = ' $ ' ;
2017-11-06 04:33:32 +00:00
2021-03-30 23:33:19 +00:00
if ( oldVariables )
2017-11-06 04:33:32 +00:00
{
2021-03-30 23:33:19 +00:00
if ( arrayIndex )
2017-11-06 04:33:32 +00:00
{
2021-04-27 02:52:58 +00:00
//if (subType == TypeReqString)
// codeStream.emit(OP_ADVANCE_STR);
2021-03-30 23:33:19 +00:00
2017-11-06 04:33:32 +00:00
codeStream . emit ( OP_LOADIMMED_IDENT ) ;
codeStream . emitSTE ( varName ) ;
2021-04-27 02:52:58 +00:00
//codeStream.emit(OP_ADVANCE_STR);
2017-11-06 04:33:32 +00:00
ip = arrayIndex - > compile ( codeStream , ip , TypeReqString ) ;
codeStream . emit ( OP_REWIND_STR ) ;
codeStream . emit ( OP_SETCURVAR_ARRAY_CREATE ) ;
2021-04-27 02:52:58 +00:00
if ( type = = TypeReqNone )
codeStream . emit ( OP_POP_STK ) ;
2021-03-30 23:33:19 +00:00
}
else
{
codeStream . emit ( OP_SETCURVAR_CREATE ) ;
codeStream . emitSTE ( varName ) ;
}
switch ( subType )
{
case TypeReqString : codeStream . emit ( OP_SAVEVAR_STR ) ; break ;
case TypeReqUInt : codeStream . emit ( OP_SAVEVAR_UINT ) ; break ;
case TypeReqFloat : codeStream . emit ( OP_SAVEVAR_FLT ) ; break ;
2017-11-06 04:33:32 +00:00
}
2012-09-19 15:15:01 +00:00
}
else
{
2021-03-30 23:33:19 +00:00
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 ) ;
}
2021-06-19 17:48:32 +00:00
codeStream . emit ( getFuncVars ( dbgLineNumber ) - > assign ( varName , subType = = TypeReqNone ? TypeReqString : subType , dbgLineNumber ) ) ;
2012-09-19 15:15:01 +00:00
}
2021-03-30 23:33:19 +00:00
2021-04-27 02:52:58 +00:00
if ( type = = TypeReqNone )
codeStream . emit ( OP_POP_STK ) ;
2012-09-19 15:15:01 +00:00
return ip ;
}
TypeReq AssignExprNode : : getPreferredType ( )
{
return expr - > getPreferredType ( ) ;
}
//------------------------------------------------------------
2021-03-30 23:33:19 +00:00
static void getAssignOpTypeOp ( S32 op , TypeReq & type , U32 & operand )
2012-09-19 15:15:01 +00:00
{
2017-11-06 04:33:32 +00:00
switch ( op )
{
2021-03-30 23:33:19 +00:00
case opPLUSPLUS :
2021-04-27 02:52:58 +00:00
TORQUE_CASE_FALLTHROUGH ;
case ' + ' :
2021-03-30 23:33:19 +00:00
type = TypeReqFloat ;
operand = OP_ADD ;
break ;
2021-04-27 02:52:58 +00:00
case opMINUSMINUS :
TORQUE_CASE_FALLTHROUGH ;
2021-03-30 23:33:19 +00:00
case ' - ' :
type = TypeReqFloat ;
operand = OP_SUB ;
break ;
case ' * ' :
type = TypeReqFloat ;
operand = OP_MUL ;
break ;
case ' / ' :
type = TypeReqFloat ;
operand = OP_DIV ;
break ;
case ' % ' :
type = TypeReqUInt ;
operand = OP_MOD ;
break ;
case ' & ' :
type = TypeReqUInt ;
operand = OP_BITAND ;
break ;
case ' ^ ' :
type = TypeReqUInt ;
operand = OP_XOR ;
break ;
case ' | ' :
type = TypeReqUInt ;
operand = OP_BITOR ;
break ;
case opSHL :
type = TypeReqUInt ;
operand = OP_SHL ;
break ;
case opSHR :
type = TypeReqUInt ;
operand = OP_SHR ;
break ;
2021-04-27 02:52:58 +00:00
default :
AssertFatal ( false , " Invalid opcode on operation expression " ) ;
2021-03-30 23:33:19 +00:00
}
}
U32 AssignOpExprNode : : compile ( CodeStream & codeStream , U32 ip , TypeReq type )
2012-09-19 15:15:01 +00:00
{
2017-11-06 04:33:32 +00:00
2012-09-19 15:15:01 +00:00
// goes like this...
2021-03-30 23:33:19 +00:00
// eval expr as float or int
// if there's an arrayIndex
// OP_LOADIMMED_IDENT
// varName
// OP_ADVANCE_STR
// eval arrayIndex stringwise
// OP_REWIND_STR
// OP_SETCURVAR_ARRAY_CREATE
// else
// OP_SETCURVAR_CREATE
// varName
// OP_LOADVAR_FLT or UINT
// operand
// OP_SAVEVAR_FLT or UINT
2017-11-06 04:33:32 +00:00
2012-09-19 15:15:01 +00:00
// conversion OP if necessary.
getAssignOpTypeOp ( op , subType , operand ) ;
2021-03-30 23:33:19 +00:00
precompileIdent ( varName ) ;
bool oldVariables = arrayIndex | | varName [ 0 ] = = ' $ ' ;
2017-11-06 04:33:32 +00:00
2021-09-07 23:43:39 +00:00
if ( op = = opPLUSPLUS & & ! oldVariables & & type = = TypeReqNone )
2012-09-19 15:15:01 +00:00
{
2021-06-19 17:48:32 +00:00
const S32 varIdx = getFuncVars ( dbgLineNumber ) - > assign ( varName , TypeReqFloat , dbgLineNumber ) ;
2017-11-06 04:33:32 +00:00
2021-03-30 23:33:19 +00:00
codeStream . emit ( OP_INC ) ;
codeStream . emit ( varIdx ) ;
2012-09-19 15:15:01 +00:00
}
else
{
2017-11-06 04:33:32 +00:00
ip = expr - > compile ( codeStream , ip , subType ) ;
2021-03-30 23:33:19 +00:00
if ( oldVariables )
2017-11-06 04:33:32 +00:00
{
2021-03-30 23:33:19 +00:00
if ( ! arrayIndex )
2017-11-06 04:33:32 +00:00
{
2021-03-30 23:33:19 +00:00
codeStream . emit ( OP_SETCURVAR_CREATE ) ;
2017-11-06 04:33:32 +00:00
codeStream . emitSTE ( varName ) ;
}
else
{
codeStream . emit ( OP_LOADIMMED_IDENT ) ;
codeStream . emitSTE ( varName ) ;
2021-04-27 02:52:58 +00:00
//codeStream.emit(OP_ADVANCE_STR);
2017-11-06 04:33:32 +00:00
ip = arrayIndex - > compile ( codeStream , ip , TypeReqString ) ;
codeStream . emit ( OP_REWIND_STR ) ;
codeStream . emit ( OP_SETCURVAR_ARRAY_CREATE ) ;
2021-04-27 02:52:58 +00:00
if ( type = = TypeReqNone )
codeStream . emit ( OP_POP_STK ) ;
2017-11-06 04:33:32 +00:00
}
2021-03-30 23:33:19 +00:00
codeStream . emit ( ( subType = = TypeReqFloat ) ? OP_LOADVAR_FLT : OP_LOADVAR_UINT ) ;
codeStream . emit ( operand ) ;
codeStream . emit ( ( subType = = TypeReqFloat ) ? OP_SAVEVAR_FLT : OP_SAVEVAR_UINT ) ;
}
else
{
const bool isFloat = subType = = TypeReqFloat ;
2021-06-19 17:48:32 +00:00
const S32 varIdx = getFuncVars ( dbgLineNumber ) - > assign ( varName , subType = = TypeReqNone ? TypeReqString : subType , dbgLineNumber ) ;
2021-03-30 23:33:19 +00:00
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 ) ;
}
2021-04-27 02:52:58 +00:00
if ( type = = TypeReqNone )
codeStream . emit ( OP_POP_STK ) ;
2012-09-19 15:15:01 +00:00
}
2014-09-07 16:38:35 +00:00
return codeStream . tell ( ) ;
2012-09-19 15:15:01 +00:00
}
TypeReq AssignOpExprNode : : getPreferredType ( )
{
getAssignOpTypeOp ( op , subType , operand ) ;
return subType ;
}
//------------------------------------------------------------
2014-09-07 16:38:35 +00:00
U32 TTagSetStmtNode : : compileStmt ( CodeStream & , U32 ip )
2012-09-19 15:15:01 +00:00
{
return ip ;
}
//------------------------------------------------------------
2014-09-07 16:38:35 +00:00
U32 TTagDerefNode : : compile ( CodeStream & , U32 ip , TypeReq )
2012-09-19 15:15:01 +00:00
{
return ip ;
}
TypeReq TTagDerefNode : : getPreferredType ( )
{
return TypeReqNone ;
}
//------------------------------------------------------------
2014-09-07 16:38:35 +00:00
U32 TTagExprNode : : compile ( CodeStream & , U32 ip , TypeReq )
2012-09-19 15:15:01 +00:00
{
return ip ;
}
TypeReq TTagExprNode : : getPreferredType ( )
{
return TypeReqNone ;
}
//------------------------------------------------------------
2021-03-30 23:33:19 +00:00
U32 FuncCallExprNode : : compile ( CodeStream & codeStream , U32 ip , TypeReq type )
2012-09-19 15:15:01 +00:00
{
// OP_PUSH_FRAME
// arg OP_PUSH arg OP_PUSH arg OP_PUSH
// eval all the args, then call the function.
2017-11-06 04:33:32 +00:00
2012-09-19 15:15:01 +00:00
// OP_CALLFUNC
// function
// namespace
// isDot
2017-11-06 04:33:32 +00:00
2012-09-19 15:15:01 +00:00
precompileIdent ( funcName ) ;
precompileIdent ( nameSpace ) ;
2017-11-06 04:33:32 +00:00
2021-03-30 23:33:19 +00:00
S32 count = 0 ;
for ( ExprNode * walk = args ; walk ; walk = static_cast < ExprNode * > ( walk - > getNext ( ) ) )
count + + ;
2017-11-06 04:33:32 +00:00
2021-03-30 23:33:19 +00:00
codeStream . emit ( OP_PUSH_FRAME ) ;
codeStream . emit ( count ) ;
2017-11-06 04:33:32 +00:00
2021-03-30 23:33:19 +00:00
for ( ExprNode * walk = args ; walk ; walk = static_cast < ExprNode * > ( walk - > getNext ( ) ) )
2012-09-19 15:15:01 +00:00
{
2014-10-27 21:55:17 +00:00
TypeReq walkType = walk - > getPreferredType ( ) ;
2021-03-30 23:33:19 +00:00
if ( walkType = = TypeReqNone )
walkType = TypeReqString ;
2014-10-27 21:55:17 +00:00
ip = walk - > compile ( codeStream , ip , walkType ) ;
2021-04-27 02:52:58 +00:00
codeStream . emit ( OP_PUSH ) ;
2012-09-19 15:15:01 +00:00
}
2017-11-06 04:33:32 +00:00
2021-03-30 23:33:19 +00:00
codeStream . emit ( OP_CALLFUNC ) ;
codeStream . emitSTE ( funcName ) ;
codeStream . emitSTE ( nameSpace ) ;
codeStream . emit ( callType ) ;
2017-11-06 04:33:32 +00:00
2021-04-27 02:52:58 +00:00
if ( type = = TypeReqNone )
codeStream . emit ( OP_POP_STK ) ;
2014-09-07 16:38:35 +00:00
return codeStream . tell ( ) ;
2012-09-19 15:15:01 +00:00
}
TypeReq FuncCallExprNode : : getPreferredType ( )
{
return TypeReqString ;
}
//------------------------------------------------------------
2021-03-30 23:33:19 +00:00
U32 AssertCallExprNode : : compile ( CodeStream & codeStream , U32 ip , TypeReq type )
2012-09-19 15:15:01 +00:00
{
2017-11-06 04:33:32 +00:00
# ifdef TORQUE_ENABLE_SCRIPTASSERTS
2012-09-19 15:15:01 +00:00
2017-11-06 04:33:32 +00:00
messageIndex = getCurrentStringTable ( ) - > add ( message , true , false ) ;
ip = testExpr - > compile ( codeStream , ip , TypeReqUInt ) ;
codeStream . emit ( OP_ASSERT ) ;
codeStream . emit ( messageIndex ) ;
# endif
2012-09-19 15:15:01 +00:00
2014-09-07 16:38:35 +00:00
return codeStream . tell ( ) ;
2012-09-19 15:15:01 +00:00
}
TypeReq AssertCallExprNode : : getPreferredType ( )
{
return TypeReqNone ;
}
//------------------------------------------------------------
2021-03-30 23:33:19 +00:00
U32 SlotAccessNode : : compile ( CodeStream & codeStream , U32 ip , TypeReq type )
2012-09-19 15:15:01 +00:00
{
2017-11-06 04:33:32 +00:00
if ( type = = TypeReqNone )
2014-09-07 16:38:35 +00:00
return ip ;
2017-11-06 04:33:32 +00:00
2012-09-19 15:15:01 +00:00
precompileIdent ( slotName ) ;
2014-09-07 16:38:35 +00:00
2021-03-30 23:33:19 +00:00
if ( arrayExpr )
2012-09-19 15:15:01 +00:00
{
2021-03-30 23:33:19 +00:00
ip = arrayExpr - > compile ( codeStream , ip , TypeReqString ) ;
2012-09-19 15:15:01 +00:00
}
2021-03-30 23:33:19 +00:00
ip = objectExpr - > compile ( codeStream , ip , TypeReqString ) ;
codeStream . emit ( OP_SETCUROBJECT ) ;
2017-11-06 04:33:32 +00:00
2021-03-30 23:33:19 +00:00
codeStream . emit ( OP_SETCURFIELD ) ;
codeStream . emitSTE ( slotName ) ;
2017-11-06 04:33:32 +00:00
2021-08-17 02:02:24 +00:00
codeStream . emit ( OP_POP_STK ) ;
2021-03-30 23:33:19 +00:00
if ( arrayExpr )
{
codeStream . emit ( OP_SETCURFIELD_ARRAY ) ;
2021-04-27 02:52:58 +00:00
codeStream . emit ( OP_POP_STK ) ;
2012-09-19 15:15:01 +00:00
}
2017-11-06 04:33:32 +00:00
switch ( type )
2012-09-19 15:15:01 +00:00
{
2021-03-30 23:33:19 +00:00
case TypeReqUInt :
codeStream . emit ( OP_LOADFIELD_UINT ) ;
break ;
case TypeReqFloat :
codeStream . emit ( OP_LOADFIELD_FLT ) ;
break ;
case TypeReqString :
codeStream . emit ( OP_LOADFIELD_STR ) ;
break ;
case TypeReqNone :
break ;
2012-09-19 15:15:01 +00:00
}
2014-09-07 16:38:35 +00:00
return codeStream . tell ( ) ;
2012-09-19 15:15:01 +00:00
}
TypeReq SlotAccessNode : : getPreferredType ( )
{
return TypeReqNone ;
}
//-----------------------------------------------------------------------------
2021-03-30 23:33:19 +00:00
U32 InternalSlotAccessNode : : compile ( CodeStream & codeStream , U32 ip , TypeReq type )
2012-09-19 15:15:01 +00:00
{
2017-11-06 04:33:32 +00:00
if ( type = = TypeReqNone )
2012-09-19 15:15:01 +00:00
return ip ;
ip = objectExpr - > compile ( codeStream , ip , TypeReqString ) ;
2014-09-07 16:38:35 +00:00
codeStream . emit ( OP_SETCUROBJECT ) ;
2012-09-19 15:15:01 +00:00
2021-08-18 00:52:59 +00:00
// we pop the stack as we will override the current object with the internal object
codeStream . emit ( OP_POP_STK ) ;
2012-09-19 15:15:01 +00:00
ip = slotExpr - > compile ( codeStream , ip , TypeReqString ) ;
2014-09-07 16:38:35 +00:00
codeStream . emit ( OP_SETCUROBJECT_INTERNAL ) ;
codeStream . emit ( recurse ) ;
2012-09-19 15:15:01 +00:00
2014-09-07 16:38:35 +00:00
return codeStream . tell ( ) ;
2012-09-19 15:15:01 +00:00
}
TypeReq InternalSlotAccessNode : : getPreferredType ( )
{
return TypeReqUInt ;
}
//-----------------------------------------------------------------------------
2021-03-30 23:33:19 +00:00
U32 SlotAssignNode : : compile ( CodeStream & codeStream , U32 ip , TypeReq type )
2012-09-19 15:15:01 +00:00
{
precompileIdent ( slotName ) ;
2017-11-06 04:33:32 +00:00
2012-09-19 15:15:01 +00:00
ip = valueExpr - > compile ( codeStream , ip , TypeReqString ) ;
2021-03-30 23:33:19 +00:00
if ( arrayExpr )
2012-09-19 15:15:01 +00:00
{
2021-03-30 23:33:19 +00:00
ip = arrayExpr - > compile ( codeStream , ip , TypeReqString ) ;
2012-09-19 15:15:01 +00:00
}
2021-03-30 23:33:19 +00:00
if ( objectExpr )
2012-09-19 15:15:01 +00:00
{
2021-03-30 23:33:19 +00:00
ip = objectExpr - > compile ( codeStream , ip , TypeReqString ) ;
codeStream . emit ( OP_SETCUROBJECT ) ;
}
else
codeStream . emit ( OP_SETCUROBJECT_NEW ) ;
codeStream . emit ( OP_SETCURFIELD ) ;
codeStream . emitSTE ( slotName ) ;
2017-11-06 04:33:32 +00:00
2021-08-17 02:02:24 +00:00
if ( objectExpr )
{
// Don't pop unless we are assigning a field to an object
// (For initializer fields, we don't wanna pop)
codeStream . emit ( OP_POP_STK ) ;
}
2021-03-30 23:33:19 +00:00
if ( arrayExpr )
{
codeStream . emit ( OP_SETCURFIELD_ARRAY ) ;
2021-04-27 02:52:58 +00:00
codeStream . emit ( OP_POP_STK ) ;
2012-09-19 15:15:01 +00:00
}
2014-09-07 16:38:35 +00:00
codeStream . emit ( OP_SAVEFIELD_STR ) ;
2012-09-19 15:15:01 +00:00
2017-11-06 04:33:32 +00:00
if ( typeID ! = - 1 )
2012-09-19 15:15:01 +00:00
{
2014-09-07 16:38:35 +00:00
codeStream . emit ( OP_SETCURFIELD_TYPE ) ;
codeStream . emit ( typeID ) ;
2012-09-19 15:15:01 +00:00
}
2021-04-27 02:52:58 +00:00
if ( type = = TypeReqNone )
codeStream . emit ( OP_POP_STK ) ;
2014-09-07 16:38:35 +00:00
return codeStream . tell ( ) ;
2012-09-19 15:15:01 +00:00
}
TypeReq SlotAssignNode : : getPreferredType ( )
{
return TypeReqString ;
}
//------------------------------------------------------------
2021-03-30 23:33:19 +00:00
U32 SlotAssignOpNode : : compile ( CodeStream & codeStream , U32 ip , TypeReq type )
2012-09-19 15:15:01 +00:00
{
// first eval the expression as its type
2017-11-06 04:33:32 +00:00
2012-09-19 15:15:01 +00:00
// if it's an array:
// eval array
// OP_ADVANCE_STR
// evaluate object expr
// OP_SETCUROBJECT
// OP_SETCURFIELD
// fieldName
// OP_TERMINATE_REWIND_STR
// OP_SETCURFIELDARRAY
2017-11-06 04:33:32 +00:00
2012-09-19 15:15:01 +00:00
// else
// evaluate object expr
// OP_SETCUROBJECT
// OP_SETCURFIELD
// fieldName
2017-11-06 04:33:32 +00:00
2012-09-19 15:15:01 +00:00
// OP_LOADFIELD of appropriate type
// operand
// OP_SAVEFIELD of appropriate type
// convert to return type if necessary.
2017-11-06 04:33:32 +00:00
2012-09-19 15:15:01 +00:00
getAssignOpTypeOp ( op , subType , operand ) ;
precompileIdent ( slotName ) ;
2017-11-06 04:33:32 +00:00
2012-09-19 15:15:01 +00:00
ip = valueExpr - > compile ( codeStream , ip , subType ) ;
2021-03-30 23:33:19 +00:00
if ( arrayExpr )
2012-09-19 15:15:01 +00:00
{
2021-03-30 23:33:19 +00:00
ip = arrayExpr - > compile ( codeStream , ip , TypeReqString ) ;
2012-09-19 15:15:01 +00:00
}
2021-03-30 23:33:19 +00:00
ip = objectExpr - > compile ( codeStream , ip , TypeReqString ) ;
codeStream . emit ( OP_SETCUROBJECT ) ;
codeStream . emit ( OP_SETCURFIELD ) ;
codeStream . emitSTE ( slotName ) ;
2017-11-06 04:33:32 +00:00
2021-08-17 02:02:24 +00:00
codeStream . emit ( OP_POP_STK ) ;
2021-03-30 23:33:19 +00:00
if ( arrayExpr )
{
codeStream . emit ( OP_SETCURFIELD_ARRAY ) ;
2021-04-27 02:52:58 +00:00
if ( subType = = TypeReqNone )
codeStream . emit ( OP_POP_STK ) ;
2012-09-19 15:15:01 +00:00
}
2014-09-07 16:38:35 +00:00
codeStream . emit ( ( subType = = TypeReqFloat ) ? OP_LOADFIELD_FLT : OP_LOADFIELD_UINT ) ;
codeStream . emit ( operand ) ;
codeStream . emit ( ( subType = = TypeReqFloat ) ? OP_SAVEFIELD_FLT : OP_SAVEFIELD_UINT ) ;
2021-06-19 16:28:32 +00:00
if ( type = = TypeReqNone )
2021-04-27 02:52:58 +00:00
codeStream . emit ( OP_POP_STK ) ;
2014-09-07 16:38:35 +00:00
return codeStream . tell ( ) ;
2012-09-19 15:15:01 +00:00
}
TypeReq SlotAssignOpNode : : getPreferredType ( )
{
getAssignOpTypeOp ( op , subType , operand ) ;
return subType ;
}
//------------------------------------------------------------
2021-03-30 23:33:19 +00:00
U32 ObjectDeclNode : : compileSubObject ( CodeStream & codeStream , U32 ip , bool root )
2012-09-19 15:15:01 +00:00
{
// goes
2017-11-06 04:33:32 +00:00
2012-09-19 15:15:01 +00:00
// OP_PUSHFRAME 1
// name expr
// OP_PUSH 1
// args... PUSH
// OP_CREATE_OBJECT 1
// parentObject 1
// isDatablock 1
// internalName 1
// isSingleton 1
// lineNumber 1
// fail point 1
2017-11-06 04:33:32 +00:00
2012-09-19 15:15:01 +00:00
// for each field, eval
// OP_ADD_OBJECT (to UINT[0]) 1
// root? 1
2017-11-06 04:33:32 +00:00
2012-09-19 15:15:01 +00:00
// add all the sub objects.
// OP_END_OBJECT 1
// root? 1
// To fix the stack issue [7/9/2007 Black]
// OP_FINISH_OBJECT <-- fail point jumps to this opcode
2017-11-06 04:33:32 +00:00
2021-03-30 23:33:19 +00:00
S32 count = 2 ; // 2 OP_PUSH's
for ( ExprNode * exprWalk = argList ; exprWalk ; exprWalk = ( ExprNode * ) exprWalk - > getNext ( ) )
count + + ;
2014-09-07 16:38:35 +00:00
codeStream . emit ( OP_PUSH_FRAME ) ;
2021-03-30 23:33:19 +00:00
codeStream . emit ( count ) ;
2012-09-19 15:15:01 +00:00
ip = classNameExpr - > compile ( codeStream , ip , TypeReqString ) ;
2014-09-07 16:38:35 +00:00
codeStream . emit ( OP_PUSH ) ;
2012-09-19 15:15:01 +00:00
ip = objectNameExpr - > compile ( codeStream , ip , TypeReqString ) ;
2014-09-07 16:38:35 +00:00
codeStream . emit ( OP_PUSH ) ;
2021-03-30 23:33:19 +00:00
for ( ExprNode * exprWalk = argList ; exprWalk ; exprWalk = ( ExprNode * ) exprWalk - > getNext ( ) )
2012-09-19 15:15:01 +00:00
{
2014-10-27 21:55:17 +00:00
TypeReq walkType = exprWalk - > getPreferredType ( ) ;
if ( walkType = = TypeReqNone ) walkType = TypeReqString ;
ip = exprWalk - > compile ( codeStream , ip , walkType ) ;
2021-04-27 02:52:58 +00:00
codeStream . emit ( OP_PUSH ) ;
2012-09-19 15:15:01 +00:00
}
2014-09-07 16:38:35 +00:00
codeStream . emit ( OP_CREATE_OBJECT ) ;
codeStream . emitSTE ( parentObject ) ;
codeStream . emit ( isDatablock ) ;
codeStream . emit ( isClassNameInternal ) ;
codeStream . emit ( isSingleton ) ;
codeStream . emit ( dbgLineNumber ) ;
const U32 failIp = codeStream . emit ( 0 ) ;
2021-03-30 23:33:19 +00:00
for ( SlotAssignNode * slotWalk = slotDecls ; slotWalk ; slotWalk = ( SlotAssignNode * ) slotWalk - > getNext ( ) )
2012-09-19 15:15:01 +00:00
ip = slotWalk - > compile ( codeStream , ip , TypeReqNone ) ;
2014-09-07 16:38:35 +00:00
codeStream . emit ( OP_ADD_OBJECT ) ;
codeStream . emit ( root ) ;
2021-03-30 23:33:19 +00:00
for ( ObjectDeclNode * objectWalk = subObjects ; objectWalk ; objectWalk = ( ObjectDeclNode * ) objectWalk - > getNext ( ) )
2012-09-19 15:15:01 +00:00
ip = objectWalk - > compileSubObject ( codeStream , ip , false ) ;
2014-09-07 16:38:35 +00:00
codeStream . emit ( OP_END_OBJECT ) ;
codeStream . emit ( root | | isDatablock ) ;
2012-09-19 15:15:01 +00:00
// Added to fix the object creation issue [7/9/2007 Black]
2014-09-07 16:38:35 +00:00
failOffset = codeStream . emit ( OP_FINISH_OBJECT ) ;
2017-11-06 04:33:32 +00:00
2014-09-07 16:38:35 +00:00
codeStream . patch ( failIp , failOffset ) ;
2017-11-06 04:33:32 +00:00
2014-09-07 16:38:35 +00:00
return codeStream . tell ( ) ;
2012-09-19 15:15:01 +00:00
}
2021-03-30 23:33:19 +00:00
U32 ObjectDeclNode : : compile ( CodeStream & codeStream , U32 ip , TypeReq type )
2012-09-19 15:15:01 +00:00
{
2014-09-07 16:38:35 +00:00
// root object decl does:
2017-11-06 04:33:32 +00:00
2014-09-07 16:38:35 +00:00
// push 0 onto the UINT stack OP_LOADIMMED_UINT
// precompiles the subObject(true)
// UINT stack now has object id
// type conv to type
2017-11-06 04:33:32 +00:00
2014-09-07 16:38:35 +00:00
codeStream . emit ( OP_LOADIMMED_UINT ) ;
codeStream . emit ( 0 ) ;
2012-09-19 15:15:01 +00:00
ip = compileSubObject ( codeStream , ip , true ) ;
2021-04-27 02:52:58 +00:00
if ( type = = TypeReqNone )
codeStream . emit ( OP_POP_STK ) ;
2014-09-07 16:38:35 +00:00
return codeStream . tell ( ) ;
}
2012-09-19 15:15:01 +00:00
TypeReq ObjectDeclNode : : getPreferredType ( )
{
return TypeReqUInt ;
}
//------------------------------------------------------------
2021-03-30 23:33:19 +00:00
U32 FunctionDeclStmtNode : : compileStmt ( CodeStream & codeStream , U32 ip )
2012-09-19 15:15:01 +00:00
{
// OP_FUNC_DECL
// func name
// namespace
// package
// hasBody?
// func end ip
// argc
// ident array[argc]
// code
// OP_RETURN_VOID
setCurrentStringTable ( & getFunctionStringTable ( ) ) ;
setCurrentFloatTable ( & getFunctionFloatTable ( ) ) ;
2017-11-06 04:33:32 +00:00
2021-03-30 23:33:19 +00:00
FuncVars vars ;
gFuncVars = & vars ;
2012-09-19 15:15:01 +00:00
argc = 0 ;
2021-03-30 23:33:19 +00:00
for ( VarNode * walk = args ; walk ; walk = ( VarNode * ) ( ( StmtNode * ) walk ) - > getNext ( ) )
2014-09-07 16:38:35 +00:00
{
precompileIdent ( walk - > varName ) ;
2021-06-19 17:48:32 +00:00
getFuncVars ( dbgLineNumber ) - > assign ( walk - > varName , TypeReqNone , dbgLineNumber ) ;
2012-09-19 15:15:01 +00:00
argc + + ;
2014-09-07 16:38:35 +00:00
}
2017-11-06 04:33:32 +00:00
2012-09-19 15:15:01 +00:00
CodeBlock : : smInFunction = true ;
2017-11-06 04:33:32 +00:00
2012-09-19 15:15:01 +00:00
precompileIdent ( fnName ) ;
precompileIdent ( nameSpace ) ;
precompileIdent ( package ) ;
2017-11-06 04:33:32 +00:00
2012-09-19 15:15:01 +00:00
CodeBlock : : smInFunction = false ;
2017-11-06 04:33:32 +00:00
2014-09-07 16:38:35 +00:00
codeStream . emit ( OP_FUNC_DECL ) ;
codeStream . emitSTE ( fnName ) ;
codeStream . emitSTE ( nameSpace ) ;
codeStream . emitSTE ( package ) ;
2017-11-06 04:33:32 +00:00
codeStream . emit ( U32 ( bool ( stmts ! = NULL ) ? 1 : 0 ) + U32 ( dbgLineNumber < < 1 ) ) ;
2014-09-07 16:38:35 +00:00
const U32 endIp = codeStream . emit ( 0 ) ;
codeStream . emit ( argc ) ;
2021-03-30 23:33:19 +00:00
const U32 localNumVarsIP = codeStream . emit ( 0 ) ;
for ( VarNode * walk = args ; walk ; walk = ( VarNode * ) ( ( StmtNode * ) walk ) - > getNext ( ) )
2012-09-19 15:15:01 +00:00
{
2021-03-30 23:33:19 +00:00
StringTableEntry name = walk - > varName ;
2021-06-19 17:48:32 +00:00
codeStream . emit ( getFuncVars ( dbgLineNumber ) - > lookup ( name , dbgLineNumber ) ) ;
2012-09-19 15:15:01 +00:00
}
CodeBlock : : smInFunction = true ;
2014-09-07 16:38:35 +00:00
ip = compileBlock ( stmts , codeStream , ip ) ;
2012-09-19 15:15:01 +00:00
// Add break so breakpoint can be set at closing brace or
// in empty function.
2014-09-07 16:38:35 +00:00
addBreakLine ( codeStream ) ;
2012-09-19 15:15:01 +00:00
CodeBlock : : smInFunction = false ;
2014-09-07 16:38:35 +00:00
codeStream . emit ( OP_RETURN_VOID ) ;
2017-11-06 04:33:32 +00:00
2021-06-19 17:48:32 +00:00
codeStream . patch ( localNumVarsIP , getFuncVars ( dbgLineNumber ) - > count ( ) ) ;
2014-09-07 16:38:35 +00:00
codeStream . patch ( endIp , codeStream . tell ( ) ) ;
2017-11-06 04:33:32 +00:00
2014-09-07 16:38:35 +00:00
setCurrentStringTable ( & getGlobalStringTable ( ) ) ;
setCurrentFloatTable ( & getGlobalFloatTable ( ) ) ;
2021-08-14 05:37:01 +00:00
// map local variables to registers for this function.
2021-09-02 02:15:37 +00:00
// Note we have to map these in order because the table itself is ordered by the register id.
2021-08-14 05:37:01 +00:00
CompilerLocalVariableToRegisterMappingTable * tbl = & getFunctionVariableMappingTable ( ) ;
2021-09-02 02:15:37 +00:00
for ( size_t i = 0 ; i < gFuncVars - > variableNameMap . size ( ) ; + + i )
2021-08-14 05:37:01 +00:00
{
2021-09-02 02:15:37 +00:00
StringTableEntry varName = gFuncVars - > variableNameMap [ i ] ;
tbl - > add ( fnName , nameSpace , varName ) ;
2021-08-14 05:37:01 +00:00
}
2021-09-21 01:00:33 +00:00
// In eval mode, global func vars are allowed.
gFuncVars = gIsEvalCompile ? & gEvalFuncVars : NULL ;
2017-11-06 04:33:32 +00:00
2012-09-19 15:15:01 +00:00
return ip ;
}