forked from Mirrors/openclonk
Script: Make non-#strict and #strict behave the same as #strict 2
This allows some simplifications, mostly code that's just not needed anymore.stable-5.2
parent
51179151ff
commit
87e12484e7
|
@ -163,17 +163,13 @@ enum C4AulBCCType
|
|||
AB_LessThanEqual, // <=
|
||||
AB_GreaterThan, // >
|
||||
AB_GreaterThanEqual, // >=
|
||||
AB_EqualIdent, // old ==
|
||||
AB_Equal, // new ==
|
||||
AB_NotEqualIdent, // old !=
|
||||
AB_NotEqual, // new !=
|
||||
AB_Equal, // ==
|
||||
AB_NotEqual, // !=
|
||||
AB_SEqual, // S=, eq
|
||||
AB_SNEqual, // ne
|
||||
AB_BitAnd, // &
|
||||
AB_BitXOr, // ^
|
||||
AB_BitOr, // |
|
||||
AB_And, // &&
|
||||
AB_Or, // ||
|
||||
AB_MulIt, // *=
|
||||
AB_DivIt, // /=
|
||||
AB_ModIt, // %=
|
||||
|
@ -326,7 +322,6 @@ class C4AulScriptFunc : public C4AulFunc
|
|||
C4ValueMapNames VarNamed; // list of named vars in this function
|
||||
C4ValueMapNames ParNamed; // list of named pars in this function
|
||||
C4V_Type ParType[C4AUL_MAX_Par]; // parameter types
|
||||
bool bNewFormat; // new func format? [ func xyz(par abc) { ... } ]
|
||||
bool bReturnRef; // return reference
|
||||
C4AulScript *pOrgScript; // the orginal script (!= Owner if included or appended)
|
||||
|
||||
|
|
|
@ -173,7 +173,7 @@ void C4AulScript::Default()
|
|||
IncludesResolved = false;
|
||||
|
||||
// defaults
|
||||
Strict = NONSTRICT;
|
||||
Strict = MAXSTRICT;
|
||||
Preparsing=Resolving=false;
|
||||
Temporary = false;
|
||||
LocalNamed.Reset();
|
||||
|
@ -390,7 +390,6 @@ void C4AulScriptFunc::CopyBody(C4AulScriptFunc &FromFunc)
|
|||
Script = FromFunc.Script;
|
||||
VarNamed = FromFunc.VarNamed;
|
||||
ParNamed = FromFunc.ParNamed;
|
||||
bNewFormat = FromFunc.bNewFormat;
|
||||
bReturnRef = FromFunc.bReturnRef;
|
||||
pOrgScript = FromFunc.pOrgScript;
|
||||
for(int i = 0; i < C4AUL_MAX_Par; i++)
|
||||
|
|
|
@ -534,15 +534,7 @@ C4Value C4AulExec::Exec(C4AulBCC *pCPos, bool fPassErrors)
|
|||
PopValue();
|
||||
break;
|
||||
}
|
||||
case AB_EqualIdent: // old ==
|
||||
{
|
||||
CheckOpPars(pCPos->Par.i);
|
||||
C4Value *pPar1 = pCurVal - 1, *pPar2 = pCurVal;
|
||||
pPar1->SetBool(pPar1->_getRaw() == pPar2->_getRaw());
|
||||
PopValue();
|
||||
break;
|
||||
}
|
||||
case AB_Equal: // new ==
|
||||
case AB_Equal: // ==
|
||||
{
|
||||
CheckOpPars(pCPos->Par.i);
|
||||
C4Value *pPar1 = pCurVal - 1, *pPar2 = pCurVal;
|
||||
|
@ -550,15 +542,7 @@ C4Value C4AulExec::Exec(C4AulBCC *pCPos, bool fPassErrors)
|
|||
PopValue();
|
||||
break;
|
||||
}
|
||||
case AB_NotEqualIdent: // old !=
|
||||
{
|
||||
CheckOpPars(pCPos->Par.i);
|
||||
C4Value *pPar1 = pCurVal - 1, *pPar2 = pCurVal;
|
||||
pPar1->SetBool(pPar1->_getRaw() != pPar2->_getRaw());
|
||||
PopValue();
|
||||
break;
|
||||
}
|
||||
case AB_NotEqual: // new !=
|
||||
case AB_NotEqual: // !=
|
||||
{
|
||||
CheckOpPars(pCPos->Par.i);
|
||||
C4Value *pPar1 = pCurVal - 1, *pPar2 = pCurVal;
|
||||
|
@ -608,22 +592,6 @@ C4Value C4AulExec::Exec(C4AulBCC *pCPos, bool fPassErrors)
|
|||
PopValue();
|
||||
break;
|
||||
}
|
||||
case AB_And: // &&
|
||||
{
|
||||
CheckOpPars(pCPos->Par.i);
|
||||
C4Value *pPar1 = pCurVal - 1, *pPar2 = pCurVal;
|
||||
pPar1->SetBool(pPar1->_getRaw() && pPar2->_getRaw());
|
||||
PopValue();
|
||||
break;
|
||||
}
|
||||
case AB_Or: // ||
|
||||
{
|
||||
CheckOpPars(pCPos->Par.i);
|
||||
C4Value *pPar1 = pCurVal - 1, *pPar2 = pCurVal;
|
||||
pPar1->SetBool(pPar1->_getRaw() || pPar2->_getRaw());
|
||||
PopValue();
|
||||
break;
|
||||
}
|
||||
case AB_MulIt: // *=
|
||||
{
|
||||
CheckOpPars(pCPos->Par.i);
|
||||
|
|
|
@ -172,8 +172,7 @@ class C4AulParseState
|
|||
const char * GetTokenName(C4AulTokenType TokenType);
|
||||
|
||||
void Warn(const char *pMsg, const char *pIdtf=0);
|
||||
void StrictError(const char *pMsg, const char *pIdtf=0);
|
||||
void Strict2Error(const char *pMsg, const char *pIdtf=0);
|
||||
void Error(const char *pMsg, const char *pIdtf=0);
|
||||
|
||||
private:
|
||||
|
||||
|
@ -236,19 +235,9 @@ void C4AulParseState::Warn(const char *pMsg, const char *pIdtf)
|
|||
++::ScriptEngine.warnCnt;
|
||||
}
|
||||
|
||||
void C4AulParseState::StrictError(const char *pMsg, const char *pIdtf)
|
||||
void C4AulParseState::Error(const char *pMsg, const char *pIdtf)
|
||||
{
|
||||
if (Fn ? (Fn->pOrgScript->Strict < C4AulScript::STRICT1) : (a->Strict < C4AulScript::STRICT1))
|
||||
Warn(pMsg, pIdtf);
|
||||
else
|
||||
throw new C4AulParseError(this, pMsg, pIdtf);
|
||||
}
|
||||
void C4AulParseState::Strict2Error(const char *pMsg, const char *pIdtf)
|
||||
{
|
||||
if (Fn ? (Fn->pOrgScript->Strict < C4AulScript::STRICT2) : (a->Strict < C4AulScript::STRICT2))
|
||||
Warn(pMsg, pIdtf);
|
||||
else
|
||||
throw new C4AulParseError(this, pMsg, pIdtf);
|
||||
throw new C4AulParseError(this, pMsg, pIdtf);
|
||||
}
|
||||
|
||||
C4AulParseError::C4AulParseError(C4AulParseState * state, const char *pMsg, const char *pIdtf, BOOL Warn)
|
||||
|
@ -457,8 +446,8 @@ C4ScriptOpDef C4ScriptOpMap[] = {
|
|||
{ 8, "&", AB_BitAnd, 1, 0, 0, C4V_Int, C4V_Int, C4V_Int},
|
||||
{ 6, "^", AB_BitXOr, 1, 0, 0, C4V_Int, C4V_Int, C4V_Int},
|
||||
{ 6, "|", AB_BitOr, 1, 0, 0, C4V_Int, C4V_Int, C4V_Int},
|
||||
{ 5, "&&", AB_And, 1, 0, 0, C4V_Bool, C4V_Bool, C4V_Bool},
|
||||
{ 4, "||", AB_Or, 1, 0, 0, C4V_Bool, C4V_Bool, C4V_Bool},
|
||||
{ 5, "&&", AB_JUMPAND, 1, 0, 0, C4V_Bool, C4V_Bool, C4V_Bool},
|
||||
{ 4, "||", AB_JUMPOR, 1, 0, 0, C4V_Bool, C4V_Bool, C4V_Bool},
|
||||
{ 2, "*=", AB_MulIt, 1, 1, 0, C4V_Any, C4V_pC4Value, C4V_Int},
|
||||
{ 2, "/=", AB_DivIt, 1, 1, 0, C4V_Any, C4V_pC4Value, C4V_Int},
|
||||
{ 2, "%=", AB_ModIt, 1, 1, 0, C4V_Any, C4V_pC4Value, C4V_Int},
|
||||
|
@ -481,20 +470,11 @@ int C4AulParseState::GetOperator(const char* pScript)
|
|||
unsigned int i;
|
||||
|
||||
if(!*pScript) return 0;
|
||||
// text with > 2 characters or text and #strict 2?
|
||||
// then break (may be misinterpreted as operator
|
||||
// operators are not alphabetical
|
||||
if((*pScript >= 'a' && *pScript <= 'z') ||
|
||||
(*pScript >= 'A' && *pScript <= 'Z'))
|
||||
{
|
||||
if(Fn ? (Fn->pOrgScript->Strict >= C4AulScript::STRICT2) : (a->Strict >= C4AulScript::STRICT2))
|
||||
return -1;
|
||||
if((*(pScript+1) >= 'a' && *(pScript+1) <= 'z') ||
|
||||
(*(pScript+1) >= 'A' && *(pScript+1) <= 'Z'))
|
||||
if((*(pScript+2) >= 'a' && *(pScript+2) <= 'z') ||
|
||||
(*(pScript+2) >= 'A' && *(pScript+2) <= 'Z') ||
|
||||
(*(pScript+2) >= '0' && *(pScript+2) <= '9') ||
|
||||
*(pScript+2) == '_')
|
||||
return -1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
// it is a two-char-operator?
|
||||
|
@ -646,14 +626,8 @@ C4AulTokenType C4AulParseState::GetNextToken(char *pToken, long int *pInt, HoldS
|
|||
// identifier by all non-special chars
|
||||
if (C >= '@')
|
||||
{
|
||||
// Old Scripts could have wacky identifier
|
||||
if (a->Strict < C4AulScript::STRICT2)
|
||||
{
|
||||
State = TGS_Ident;
|
||||
break;
|
||||
}
|
||||
// But now only the alphabet and '_' is allowed
|
||||
else if ((C >= 'A' && C <= 'Z') || (C >= 'a' && C <= 'z') || (C == '_'))
|
||||
// only the alphabet and '_' is allowed
|
||||
if ((C >= 'A' && C <= 'Z') || (C >= 'a' && C <= 'z') || (C == '_'))
|
||||
{
|
||||
State = TGS_Ident;
|
||||
break;
|
||||
|
@ -757,12 +731,6 @@ C4AulTokenType C4AulParseState::GetNextToken(char *pToken, long int *pInt, HoldS
|
|||
// return integer
|
||||
Len = Min(Len, C4AUL_MAX_Identifier);
|
||||
SCopy(SPos0, pToken, Len);
|
||||
// or is it a func label?
|
||||
if ((C == '(') || (C == ':'))
|
||||
{
|
||||
Strict2Error("stupid func label: ", pToken);
|
||||
return ATT_IDTF;
|
||||
}
|
||||
// do not parse 0x prefix for hex
|
||||
if (State == TGS_IntHex) pToken += 2;
|
||||
// it's not, so return the int
|
||||
|
@ -779,12 +747,6 @@ C4AulTokenType C4AulParseState::GetNextToken(char *pToken, long int *pInt, HoldS
|
|||
// return C4ID string
|
||||
Len = Min(Len, C4AUL_MAX_Identifier);
|
||||
SCopy(SPos0, pToken, Len);
|
||||
// another stupid label identifier?
|
||||
if ((C == '(') || (C == ':' && *(SPos+1) != ':'))
|
||||
{
|
||||
Strict2Error("stupid func label: ", pToken);
|
||||
return ATT_IDTF;
|
||||
}
|
||||
// check if valid
|
||||
if (!LooksLikeID(pToken)) throw new C4AulParseError(this, "erroneous Ident: ", pToken);
|
||||
// get id of it
|
||||
|
@ -886,17 +848,13 @@ static const char * GetTTName(C4AulBCCType e)
|
|||
case AB_LessThanEqual: return "LessThanEqual"; // <=
|
||||
case AB_GreaterThan: return "GreaterThan"; // >
|
||||
case AB_GreaterThanEqual: return "GreaterThanEqual"; // >=
|
||||
case AB_EqualIdent: return "EqualIdent"; // old ==
|
||||
case AB_Equal: return "Equal"; // new ==
|
||||
case AB_NotEqualIdent: return "NotEqualIdent"; // old !=
|
||||
case AB_NotEqual: return "NotEqual"; // new !=
|
||||
case AB_Equal: return "Equal"; // ==
|
||||
case AB_NotEqual: return "NotEqual"; // !=
|
||||
case AB_SEqual: return "SEqual"; // S=, eq
|
||||
case AB_SNEqual: return "SNEqual"; // ne
|
||||
case AB_BitAnd: return "BitAnd"; // &
|
||||
case AB_BitXOr: return "BitXOr"; // ^
|
||||
case AB_BitOr: return "BitOr"; // |
|
||||
case AB_And: return "And"; // &&
|
||||
case AB_Or: return "Or"; // ||
|
||||
case AB_MulIt: return "MulIt"; // *=
|
||||
case AB_DivIt: return "DivIt"; // /=
|
||||
case AB_ModIt: return "ModIt"; // %=
|
||||
|
@ -1005,7 +963,7 @@ BOOL C4AulScript::Preparse()
|
|||
state.Parse_Script();
|
||||
|
||||
// no #strict? we don't like that :(
|
||||
if (!Strict)
|
||||
if (Strict < MAXSTRICT)
|
||||
{
|
||||
Engine->nonStrictCnt++;
|
||||
}
|
||||
|
@ -1057,16 +1015,12 @@ void C4AulParseState::AddBCC(C4AulBCCType eType, intptr_t X)
|
|||
case AB_GreaterThan:
|
||||
case AB_GreaterThanEqual:
|
||||
case AB_Equal:
|
||||
case AB_EqualIdent:
|
||||
case AB_NotEqual:
|
||||
case AB_NotEqualIdent:
|
||||
case AB_SEqual:
|
||||
case AB_SNEqual:
|
||||
case AB_BitAnd:
|
||||
case AB_BitXOr:
|
||||
case AB_BitOr:
|
||||
case AB_And:
|
||||
case AB_Or:
|
||||
case AB_MulIt:
|
||||
case AB_DivIt:
|
||||
case AB_ModIt:
|
||||
|
@ -1526,7 +1480,7 @@ void C4AulParseState::Parse_FuncHead()
|
|||
if (a->Engine->GlobalNamedNames.GetItemNr(Idtf) != -1)
|
||||
throw new C4AulParseError(this, "function definition: name already in use (global variable)");
|
||||
if (a->Engine->GlobalConstNames.GetItemNr(Idtf) != -1)
|
||||
Strict2Error("function definition: name already in use (global variable)", 0);
|
||||
Error("function definition: name already in use (global constant)", 0);
|
||||
}
|
||||
// create script fn
|
||||
if (Acc == AA_GLOBAL)
|
||||
|
@ -1545,7 +1499,7 @@ void C4AulParseState::Parse_FuncHead()
|
|||
// set up func (in the case we got an error)
|
||||
Fn->Script = SPos; // temporary
|
||||
Fn->Access = Acc; Fn->pOrgScript = a;
|
||||
Fn->bNewFormat = true; Fn->bReturnRef = bReturnRef;
|
||||
Fn->bReturnRef = bReturnRef;
|
||||
Shift(Discard,false);
|
||||
// expect an opening bracket now
|
||||
if (TokenType != ATT_BOPEN)
|
||||
|
@ -1572,11 +1526,6 @@ void C4AulParseState::Parse_FuncHead()
|
|||
{
|
||||
UnexpectedToken("parameter or closing bracket");
|
||||
}
|
||||
char TypeIdtf[C4AUL_MAX_Identifier] = ""; // current identifier
|
||||
if (TokenType == ATT_IDTF)
|
||||
{
|
||||
SCopy(Idtf, TypeIdtf);
|
||||
}
|
||||
// type identifier?
|
||||
if (SEqual(Idtf, C4AUL_TypeInt)) { Fn->ParType[cpar] = C4V_Int; Shift(Discard,false); }
|
||||
else if (SEqual(Idtf, C4AUL_TypeBool)) { Fn->ParType[cpar] = C4V_Bool; Shift(Discard,false); }
|
||||
|
@ -1589,12 +1538,7 @@ void C4AulParseState::Parse_FuncHead()
|
|||
if (TokenType == ATT_AMP) { Fn->ParType[cpar] = C4V_pC4Value; Shift(Discard,false); }
|
||||
if (TokenType != ATT_IDTF)
|
||||
{
|
||||
if (SEqual(TypeIdtf,""))
|
||||
UnexpectedToken("parameter or closing bracket");
|
||||
// A parameter with the same name as a type
|
||||
Strict2Error("parameter has the same name as type ", TypeIdtf);
|
||||
Fn->ParType[cpar] = C4V_Any;
|
||||
Fn->ParNamed.AddName(TypeIdtf);
|
||||
UnexpectedToken("parameter name");
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1614,132 +1558,14 @@ void C4AulParseState::Parse_FuncHead()
|
|||
Shift(Discard,false);
|
||||
cpar++;
|
||||
}
|
||||
// ok, expect opening block
|
||||
if(TokenType != ATT_BLOPEN)
|
||||
{
|
||||
// warn
|
||||
Strict2Error("'func': expecting opening block ('{') after func declaration", 0);
|
||||
// not really new syntax (a sort of legacy mode)
|
||||
Fn->bNewFormat = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
Fn->Script = SPos;
|
||||
Shift();
|
||||
}
|
||||
Fn->Script = SPos;
|
||||
Match(ATT_BLOPEN);
|
||||
Parse_Desc();
|
||||
Parse_Function();
|
||||
Match(ATT_BLCLOSE);
|
||||
return;
|
||||
}
|
||||
// Must be old-style function declaration now
|
||||
if (a->Strict >= C4AulScript::STRICT2)
|
||||
throw new C4AulParseError(this, "Declaration expected, but found identifier ", Idtf);
|
||||
// check: symbol already in use?
|
||||
switch(Acc)
|
||||
{
|
||||
case AA_PRIVATE:
|
||||
case AA_PROTECTED:
|
||||
case AA_PUBLIC:
|
||||
if(a->LocalNamed.GetItemNr(Idtf) != -1)
|
||||
throw new C4AulParseError(this, "function definition: name already in use (local variable)");
|
||||
if(a->Def)
|
||||
break;
|
||||
// func in global context: fallthru
|
||||
case AA_GLOBAL:
|
||||
if(a->Engine->GlobalNamedNames.GetItemNr(Idtf) != -1)
|
||||
throw new C4AulParseError(this, "function definition: name already in use (global variable)");
|
||||
}
|
||||
char FuncIdtf[C4AUL_MAX_Identifier] = ""; // current identifier
|
||||
SCopy(Idtf, FuncIdtf);
|
||||
Shift();
|
||||
if (TokenType != ATT_COLON)
|
||||
throw new C4AulParseError(this, FormatString("declaration expected, but found identifier '%s'", FuncIdtf).getData());
|
||||
// create script fn
|
||||
if (Acc == AA_GLOBAL)
|
||||
{
|
||||
// global func
|
||||
Fn = new C4AulScriptFunc(a->Engine, FuncIdtf);
|
||||
C4AulFunc *FnLink = new C4AulFunc(a, NULL);
|
||||
FnLink->LinkedTo = Fn; Fn->LinkedTo = FnLink;
|
||||
Acc = AA_PUBLIC;
|
||||
}
|
||||
else
|
||||
{
|
||||
// normal, local func
|
||||
Fn = new C4AulScriptFunc(a, FuncIdtf);
|
||||
}
|
||||
Fn->Script = SPos;
|
||||
Fn->Access = Acc;
|
||||
Fn->pOrgScript = a;
|
||||
Fn->bNewFormat = false;
|
||||
Fn->bReturnRef = false;
|
||||
Shift();
|
||||
Parse_Desc();
|
||||
const char * SPos0 = SPos;
|
||||
while(1) switch(TokenType)
|
||||
{
|
||||
// end of function
|
||||
case ATT_EOF: case ATT_DIR: return;
|
||||
case ATT_IDTF:
|
||||
{
|
||||
// check for func declaration
|
||||
if (SEqual(Idtf, C4AUL_Private)) return;
|
||||
else if (SEqual(Idtf, C4AUL_Protected)) return;
|
||||
else if (SEqual(Idtf, C4AUL_Public)) return;
|
||||
else if (SEqual(Idtf, C4AUL_Global)) return;
|
||||
else if (SEqual(Idtf, C4AUL_Func)) return;
|
||||
// check for variable definition (var)
|
||||
else if(SEqual(Idtf, C4AUL_VarNamed))
|
||||
{
|
||||
Shift();
|
||||
Parse_Var();
|
||||
}
|
||||
// check for variable definition (local)
|
||||
else if(SEqual(Idtf, C4AUL_LocalNamed))
|
||||
{
|
||||
if(a->Def)
|
||||
{
|
||||
Shift();
|
||||
Parse_Local();
|
||||
}
|
||||
else
|
||||
throw new C4AulParseError(this, "'local' variable declaration in global script");
|
||||
}
|
||||
// check for variable definition (static)
|
||||
else if(SEqual(Idtf, C4AUL_GlobalNamed))
|
||||
{
|
||||
Shift();
|
||||
Parse_Static();
|
||||
}
|
||||
// might be old style declaration
|
||||
else
|
||||
{
|
||||
const char * SPos0_ = SPos;
|
||||
Shift();
|
||||
if (TokenType == ATT_COLON)
|
||||
{
|
||||
// Reset source position to the point before the label
|
||||
SPos = SPos0;
|
||||
Shift();
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
// The current token might be a label
|
||||
// In that case the next round of the loop will need to reset the position to what's in SPos0_ now
|
||||
SPos0 = SPos0_;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
SPos0 = SPos;
|
||||
Shift();
|
||||
break;
|
||||
}
|
||||
}
|
||||
throw new C4AulParseError(this, "Declaration expected, but found identifier ", Idtf);
|
||||
}
|
||||
|
||||
void C4AulParseState::Parse_Desc()
|
||||
|
@ -1785,23 +1611,18 @@ void C4AulParseState::Parse_Function()
|
|||
// a block end?
|
||||
case ATT_BLCLOSE:
|
||||
{
|
||||
// new-form func?
|
||||
if(Fn->bNewFormat)
|
||||
// all ok, insert a return
|
||||
C4AulBCC * CPos = a->GetCodeByPos(Max(a->GetCodePos() - 1,0));
|
||||
if (!CPos || CPos->bccType != AB_RETURN || fJump)
|
||||
{
|
||||
// all ok, insert a return
|
||||
C4AulBCC * CPos = a->GetCodeByPos(Max(a->GetCodePos() - 1,0));
|
||||
if (!CPos || CPos->bccType != AB_RETURN || fJump)
|
||||
{
|
||||
AddBCC(AB_INT);
|
||||
AddBCC(AB_RETURN);
|
||||
}
|
||||
// and break
|
||||
Done = TRUE;
|
||||
// Do not blame this function for script errors between functions
|
||||
Fn = 0;
|
||||
return;
|
||||
AddBCC(AB_INT);
|
||||
AddBCC(AB_RETURN);
|
||||
}
|
||||
throw new C4AulParseError(this, "no '{' found for '}'");
|
||||
// and break
|
||||
Done = TRUE;
|
||||
// Do not blame this function for script errors between functions
|
||||
Fn = 0;
|
||||
return;
|
||||
}
|
||||
case ATT_EOF:
|
||||
{
|
||||
|
@ -1967,23 +1788,11 @@ void C4AulParseState::Parse_Statement()
|
|||
}
|
||||
else if (SEqual(Idtf, C4AUL_Return)) // return
|
||||
{
|
||||
bool multi_params_hack = false;
|
||||
Shift();
|
||||
if (TokenType == ATT_BOPEN && Fn->pOrgScript->Strict < C4AulScript::STRICT2)
|
||||
if(TokenType == ATT_SCOLON)
|
||||
{
|
||||
// parse return(retvals) - return(retval, unused, parameters, ...) allowed for backwards compatibility
|
||||
if (Parse_Params(1, NULL) == 1)
|
||||
{
|
||||
// return (1 + 1) * 3 returns 6, not 2
|
||||
Parse_Expression2();
|
||||
}
|
||||
else
|
||||
multi_params_hack = true;
|
||||
}
|
||||
else if(TokenType == ATT_SCOLON)
|
||||
{
|
||||
// allow return; without return value (implies 0)
|
||||
AddBCC(AB_INT);
|
||||
// allow return; without return value (implies nil)
|
||||
AddBCC(AB_NIL);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1993,15 +1802,6 @@ void C4AulParseState::Parse_Statement()
|
|||
if(!Fn->bReturnRef)
|
||||
SetNoRef();
|
||||
AddBCC(AB_RETURN);
|
||||
if (multi_params_hack && TokenType != ATT_SCOLON)
|
||||
{
|
||||
// return (1, 1) * 3 returns 1
|
||||
// but warn about it, the * 3 won't get executed and a stray ',' could lead to unexpected results
|
||||
Warn("';' expected, but found ", GetTokenName(TokenType));
|
||||
AddBCC(AB_STACK, +1);
|
||||
Parse_Expression2();
|
||||
AddBCC(AB_STACK, -1);
|
||||
}
|
||||
}
|
||||
else if (SEqual(Idtf, C4AUL_this)) // this on top level
|
||||
{
|
||||
|
@ -2017,7 +1817,7 @@ void C4AulParseState::Parse_Statement()
|
|||
// Must be inside a loop
|
||||
if(!pLoopStack)
|
||||
{
|
||||
Strict2Error("'break' is only allowed inside loops");
|
||||
Error("'break' is only allowed inside loops");
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -2037,7 +1837,7 @@ void C4AulParseState::Parse_Statement()
|
|||
// Must be inside a loop
|
||||
if(!pLoopStack)
|
||||
{
|
||||
Strict2Error("'continue' is only allowed inside loops");
|
||||
Error("'continue' is only allowed inside loops");
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -2093,23 +1893,14 @@ void C4AulParseState::Parse_Statement()
|
|||
}
|
||||
else
|
||||
{
|
||||
bool gotohack = false;
|
||||
// none of these? then it's a function
|
||||
// if it's a label, it will be missinterpreted here, which will be corrected later
|
||||
// it may be the first goto() found? (old syntax only!)
|
||||
if (SEqual(Idtf, C4AUL_Goto) && !Fn->pOrgScript->Strict)
|
||||
// add AB_RETURN later on
|
||||
gotohack=true;
|
||||
C4AulFunc *FoundFn;
|
||||
// old syntax: do not allow recursive calls in overloaded functions
|
||||
if (!Fn->pOrgScript->Strict && Fn->OwnerOverloaded && SEqual(Idtf, Fn->Name))
|
||||
FoundFn = Fn->OwnerOverloaded;
|
||||
// get regular function
|
||||
if(Fn->Owner == &::ScriptEngine)
|
||||
FoundFn = a->Owner->GetFuncRecursive(Idtf);
|
||||
else
|
||||
// get regular function
|
||||
if(Fn->Owner == &::ScriptEngine)
|
||||
FoundFn = a->Owner->GetFuncRecursive(Idtf);
|
||||
else
|
||||
FoundFn = a->GetFuncRecursive(Idtf);
|
||||
FoundFn = a->GetFuncRecursive(Idtf);
|
||||
// ignore func-not-found errors in the preparser, because the function tables are not built yet
|
||||
if (!FoundFn && Type == PARSER)
|
||||
{
|
||||
|
@ -2138,11 +1929,6 @@ void C4AulParseState::Parse_Statement()
|
|||
if (TokenType == ATT_BOPEN || Type == PARSER)
|
||||
Parse_Params(FoundFn ? FoundFn->GetParCount() : 10, FoundFn ? FoundFn->Name : Idtf, FoundFn);
|
||||
AddBCC(AB_FUNC, (long) FoundFn);
|
||||
if (gotohack)
|
||||
{
|
||||
AddBCC(AB_RETURN);
|
||||
AddBCC(AB_STACK, +1);
|
||||
}
|
||||
Parse_Expression2();
|
||||
SetNoRef();
|
||||
AddBCC(AB_STACK, -1);
|
||||
|
@ -2352,14 +2138,9 @@ void C4AulParseState::Parse_While()
|
|||
// Save position for later jump back
|
||||
int iStart = JumpHere();
|
||||
// Execute condition
|
||||
if (Fn->pOrgScript->Strict >= C4AulScript::STRICT2)
|
||||
{
|
||||
Match(ATT_BOPEN);
|
||||
Parse_Expression();
|
||||
Match(ATT_BCLOSE);
|
||||
}
|
||||
else
|
||||
Parse_Params(1, C4AUL_While);
|
||||
Match(ATT_BOPEN);
|
||||
Parse_Expression();
|
||||
Match(ATT_BCLOSE);
|
||||
SetNoRef();
|
||||
// Check condition
|
||||
int iCond = a->GetCodePos();
|
||||
|
@ -2384,14 +2165,9 @@ void C4AulParseState::Parse_While()
|
|||
|
||||
void C4AulParseState::Parse_If()
|
||||
{
|
||||
if (Fn->pOrgScript->Strict >= C4AulScript::STRICT2)
|
||||
{
|
||||
Match(ATT_BOPEN);
|
||||
Parse_Expression();
|
||||
Match(ATT_BCLOSE);
|
||||
}
|
||||
else
|
||||
Parse_Params(1, C4AUL_If);
|
||||
Match(ATT_BOPEN);
|
||||
Parse_Expression();
|
||||
Match(ATT_BCLOSE);
|
||||
SetNoRef();
|
||||
// create bytecode, remember position
|
||||
int iCond = a->GetCodePos();
|
||||
|
@ -2599,12 +2375,7 @@ void C4AulParseState::Parse_Expression(int iParentPrio)
|
|||
throw new C4AulParseError(this, "'for' may not be used as a parameter");
|
||||
else if (SEqual(Idtf, C4AUL_Return))
|
||||
{
|
||||
// return: treat as regular function with special byte code
|
||||
Strict2Error("return used as a parameter", 0);
|
||||
Shift();
|
||||
Parse_Params(1, NULL);
|
||||
AddBCC(AB_RETURN);
|
||||
AddBCC(AB_STACK, +1);
|
||||
Error("return may not be used as a parameter", 0);
|
||||
}
|
||||
else if (SEqual(Idtf, C4AUL_Par))
|
||||
{
|
||||
|
@ -2616,8 +2387,6 @@ void C4AulParseState::Parse_Expression(int iParentPrio)
|
|||
else if (SEqual(Idtf, C4AUL_Inherited) || SEqual(Idtf, C4AUL_SafeInherited))
|
||||
{
|
||||
Shift();
|
||||
// inherited keyword: check strict syntax
|
||||
if (!Fn->pOrgScript->Strict) throw new C4AulParseError(this, "inherited disabled; use #strict syntax!");
|
||||
// get function
|
||||
if (Fn->OwnerOverloaded)
|
||||
{
|
||||
|
@ -2628,7 +2397,7 @@ void C4AulParseState::Parse_Expression(int iParentPrio)
|
|||
else
|
||||
// not found? raise an error, if it's not a safe call
|
||||
if (SEqual(Idtf, C4AUL_Inherited) && Type == PARSER)
|
||||
throw new C4AulParseError(this, "inherited function not found, use _inherited to call failsafe");
|
||||
throw new C4AulParseError(this, "inherited function not found (use _inherited to disable this message)");
|
||||
else
|
||||
{
|
||||
// otherwise, parse parameters, but discard them
|
||||
|
@ -2637,13 +2406,6 @@ void C4AulParseState::Parse_Expression(int iParentPrio)
|
|||
AddBCC(AB_STACK, 1);
|
||||
}
|
||||
}
|
||||
else if (!Fn->pOrgScript->Strict && Fn->OwnerOverloaded && SEqual(Idtf, Fn->Name))
|
||||
{
|
||||
// old syntax: do not allow recursive calls in overloaded functions
|
||||
Shift();
|
||||
Parse_Params(Fn->OwnerOverloaded->GetParCount(), Fn->Name, Fn);
|
||||
AddBCC(AB_FUNC, (long) Fn->OwnerOverloaded);
|
||||
}
|
||||
else
|
||||
{
|
||||
C4AulFunc *FoundFn;
|
||||
|
@ -2701,14 +2463,6 @@ void C4AulParseState::Parse_Expression(int iParentPrio)
|
|||
}
|
||||
}
|
||||
Shift();
|
||||
// now let's check whether it used old- or new-style
|
||||
if (TokenType == ATT_BOPEN && Fn->pOrgScript->Strict < C4AulScript::STRICT2)
|
||||
{
|
||||
// old-style usage: ignore function call
|
||||
// must not use parameters here (although generating the byte code for that would be possible)
|
||||
Shift();
|
||||
Match(ATT_BCLOSE, "parameters not allowed in functional usage of constants");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -2785,9 +2539,6 @@ void C4AulParseState::Parse_Expression(int iParentPrio)
|
|||
}
|
||||
case ATT_BOPEN2:
|
||||
{
|
||||
// Arrays are not tested in non-strict mode at all
|
||||
if(!Fn->pOrgScript->Strict)
|
||||
throw new C4AulParseError(this, "unexpected '['");
|
||||
Parse_Array();
|
||||
break;
|
||||
}
|
||||
|
@ -2840,12 +2591,12 @@ void C4AulParseState::Parse_Expression2(int iParentPrio)
|
|||
SetNoRef();
|
||||
Shift();
|
||||
|
||||
if ((C4ScriptOpMap[OpID].Code == AB_And || C4ScriptOpMap[OpID].Code == AB_Or) && Fn->pOrgScript->Strict >= C4AulScript::STRICT2)
|
||||
if (C4ScriptOpMap[OpID].Code == AB_JUMPAND || C4ScriptOpMap[OpID].Code == AB_JUMPOR)
|
||||
{
|
||||
// create bytecode, remember position
|
||||
int iCond = a->GetCodePos();
|
||||
// Jump or discard first parameter
|
||||
AddBCC(C4ScriptOpMap[OpID].Code == AB_And ? AB_JUMPAND : AB_JUMPOR);
|
||||
AddBCC(C4ScriptOpMap[OpID].Code);
|
||||
// parse second expression
|
||||
Parse_Expression(C4ScriptOpMap[OpID].Priority);
|
||||
// set condition jump target
|
||||
|
@ -2857,38 +2608,18 @@ void C4AulParseState::Parse_Expression2(int iParentPrio)
|
|||
// expect second parameter for operator
|
||||
if(!C4ScriptOpMap[OpID].NoSecondStatement)
|
||||
{
|
||||
switch (TokenType)
|
||||
{
|
||||
case ATT_IDTF: case ATT_INT: case ATT_BOOL: case ATT_STRING: case ATT_C4ID: case ATT_NIL:
|
||||
case ATT_OPERATOR: case ATT_BOPEN: case ATT_BOPEN2:
|
||||
Parse_Expression(C4ScriptOpMap[OpID].Priority);
|
||||
// If the operator does not modify the second argument, no reference is necessary
|
||||
if(C4ScriptOpMap[OpID].Type2 != C4V_pC4Value)
|
||||
SetNoRef();
|
||||
break;
|
||||
default:
|
||||
// Stuff like foo(42+,1) used to silently work
|
||||
Strict2Error(FormatString("Operator %s: Second expression expected, but %s found",
|
||||
C4ScriptOpMap[OpID].Identifier, GetTokenName(TokenType)).getData(), NULL);
|
||||
AddBCC(AB_INT, 0);
|
||||
break;
|
||||
}
|
||||
Parse_Expression(C4ScriptOpMap[OpID].Priority);
|
||||
// If the operator does not modify the second argument, no reference is necessary
|
||||
if(C4ScriptOpMap[OpID].Type2 != C4V_pC4Value)
|
||||
SetNoRef();
|
||||
}
|
||||
// write byte code, with a few backward compat changes
|
||||
if (C4ScriptOpMap[OpID].Code == AB_Equal && Fn->pOrgScript->Strict < C4AulScript::STRICT2)
|
||||
AddBCC(AB_EqualIdent, OpID);
|
||||
else if (C4ScriptOpMap[OpID].Code == AB_NotEqual && Fn->pOrgScript->Strict < C4AulScript::STRICT2)
|
||||
AddBCC(AB_NotEqualIdent, OpID);
|
||||
else
|
||||
AddBCC(C4ScriptOpMap[OpID].Code, OpID);
|
||||
// write byte code
|
||||
AddBCC(C4ScriptOpMap[OpID].Code, OpID);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ATT_BOPEN2:
|
||||
{
|
||||
// Arrays are not tested in non-strict mode at all
|
||||
if(!Fn->pOrgScript->Strict)
|
||||
throw new C4AulParseError(this, "unexpected '['");
|
||||
// Access the array
|
||||
Shift();
|
||||
Parse_Expression();
|
||||
|
@ -3073,10 +2804,10 @@ void C4AulParseState::Parse_Static()
|
|||
UnexpectedToken("variable name");
|
||||
// global variable definition
|
||||
// check: symbol already in use?
|
||||
if(a->Engine->GetFuncRecursive(Idtf)) throw new C4AulParseError(this, "variable definition: name already in use");
|
||||
if (a->Engine->GetGlobalConstant(Idtf, NULL)) Strict2Error("constant and variable with name ", Idtf);
|
||||
if (a->Engine->GetFuncRecursive(Idtf)) Error("function and variable with name ", Idtf);
|
||||
if (a->Engine->GetGlobalConstant(Idtf, NULL)) Error("constant and variable with name ", Idtf);
|
||||
// insert variable if not defined already
|
||||
if(a->Engine->GlobalNamedNames.GetItemNr(Idtf) == -1)
|
||||
if (a->Engine->GlobalNamedNames.GetItemNr(Idtf) == -1)
|
||||
a->Engine->GlobalNamedNames.AddName(Idtf);
|
||||
}
|
||||
Match(ATT_IDTF);
|
||||
|
@ -3113,9 +2844,9 @@ void C4AulParseState::Parse_Const()
|
|||
// (e.g., for overloading constants such as OCF_Living() in chaos scenarios)
|
||||
// it is not encouraged though, so better warn
|
||||
if(a->Engine->GetFuncRecursive(Idtf))
|
||||
Strict2Error("definition of constant hidden by function ", Idtf);
|
||||
Error("definition of constant hidden by function ", Idtf);
|
||||
if(a->Engine->GlobalNamedNames.GetItemNr(Idtf) != -1)
|
||||
Strict2Error("constant and variable with name ", Idtf);
|
||||
Error("constant and variable with name ", Idtf);
|
||||
Match(ATT_IDTF);
|
||||
// expect '='
|
||||
if (TokenType != ATT_OPERATOR || !SEqual(C4ScriptOpMap[cInt].Identifier,"="))
|
||||
|
@ -3309,7 +3040,7 @@ void C4AulScript::ParseDescs()
|
|||
C4AulScript *C4AulScript::FindFirstNonStrictScript()
|
||||
{
|
||||
// self is not #strict?
|
||||
if (Script && !Strict) return this;
|
||||
if (Script && Strict < MAXSTRICT) return this;
|
||||
// search children
|
||||
C4AulScript *pNonStrScr;
|
||||
for (C4AulScript *pScr=Child0; pScr; pScr=pScr->Next)
|
||||
|
|
|
@ -1911,8 +1911,6 @@ static C4Object *FnCreateObject(C4AulContext *cthr,
|
|||
{
|
||||
iXOffset+=cthr->Obj->GetX();
|
||||
iYOffset+=cthr->Obj->GetY();
|
||||
if (!cthr->Caller || !cthr->Caller->Func->Owner->Strict)
|
||||
iOwner=cthr->Obj->Owner;
|
||||
}
|
||||
|
||||
C4Object *pNewObj = Game.CreateObject(PropList,cthr->Obj,iOwner,iXOffset,iYOffset);
|
||||
|
@ -1932,8 +1930,6 @@ static C4Object *FnCreateConstruction(C4AulContext *cthr,
|
|||
{
|
||||
iXOffset+=cthr->Obj->GetX();
|
||||
iYOffset+=cthr->Obj->GetY();
|
||||
if (!cthr->Caller || !cthr->Caller->Func->Owner->Strict)
|
||||
iOwner=cthr->Obj->Owner;
|
||||
}
|
||||
|
||||
// Check site
|
||||
|
|
Loading…
Reference in New Issue