Sun, 09 Feb 2014 14:56:58 +0200
- variables: merged const and mutable variables into one system, added constexpr variable support. still no locals
src/Expression.cc | file | annotate | diff | comparison | revisions | |
src/LexerScanner.cc | file | annotate | diff | comparison | revisions | |
src/Parser.cc | file | annotate | diff | comparison | revisions | |
src/Parser.h | file | annotate | diff | comparison | revisions | |
src/Tokens.h | file | annotate | diff | comparison | revisions | |
src/Variables.cc | file | annotate | diff | comparison | revisions | |
src/Variables.h | file | annotate | diff | comparison | revisions |
--- a/src/Expression.cc Sun Feb 09 14:34:13 2014 +0200 +++ b/src/Expression.cc Sun Feb 09 14:56:58 2014 +0200 @@ -77,7 +77,6 @@ try { - ScriptVariable* globalvar; mLexer->MustGetNext(); if (mLexer->GetTokenType() == tkColon) @@ -108,43 +107,29 @@ return op; } - // Check constant - if (ConstantInfo* constant = mParser->FindConstant (GetTokenString())) + // Check global variable + // TODO: handle locals too when they're implemented + if (mLexer->GetTokenType() == tkDollarSign) { - if (mType != constant->type) - Error ("constant `%1` is %2, expression requires %3\n", - constant->name, GetTypeName (constant->type), - GetTypeName (mType)); + mLexer->MustGetNext (tkSymbol); + ScriptVariable* globalvar = FindGlobalVariable (GetTokenString()); - switch (constant->type) + if (globalvar == null) + Error ("unknown variable %1", GetTokenString()); + + if (globalvar->writelevel == ScriptVariable::WRITE_Constexpr) + op->SetValue (globalvar->value); + else { - case EBoolType: - case EIntType: - op->SetValue (constant->val.ToLong()); - break; - - case EStringType: - op->SetValue (GetStringTableIndex (constant->val)); - break; - - case EVoidType: - case EUnknownType: - break; + DataBuffer* buf = new DataBuffer (8); + buf->WriteDWord (dhPushGlobalVar); + buf->WriteDWord (globalvar->index); + op->SetBuffer (buf); } return op; } - // Check global variable - if ((globalvar = FindGlobalVariable (GetTokenString()))) - { - DataBuffer* buf = new DataBuffer (8); - buf->WriteDWord (dhPushGlobalVar); - buf->WriteDWord (globalvar->index); - op->SetBuffer (buf); - return op; - } - EToken tt; // Check for literal
--- a/src/LexerScanner.cc Sun Feb 09 14:34:13 2014 +0200 +++ b/src/LexerScanner.cc Sun Feb 09 14:56:58 2014 +0200 @@ -102,6 +102,7 @@ "state", "switch", "str", + "var", "void", "while", "true",
--- a/src/Parser.cc Sun Feb 09 14:34:13 2014 +0200 +++ b/src/Parser.cc Sun Feb 09 14:56:58 2014 +0200 @@ -117,10 +117,8 @@ ParseOnEnterExit(); break; - case tkInt: - case tkStr: - case tkVoid: - ParseVariableDeclaration(); + case tkVar: + ParseVar(); break; case tkGoto: @@ -171,10 +169,6 @@ ParseBlockEnd(); break; - case tkConst: - ParseConst(); - break; - case tkEventdef: ParseEventdef(); break; @@ -328,9 +322,12 @@ // ============================================================================ // -void BotscriptParser::ParseVariableDeclaration() +void BotscriptParser::ParseVar() { - // For now, only globals are supported + const bool isconst = mLexer->GetNext (tkConst); + mLexer->MustGetAnyOf ({tkInt, tkStr, tkVoid}); + + // TODO if (mCurrentMode != ETopLevelMode || mCurrentState.IsEmpty() == false) Error ("variables must only be global for now"); @@ -341,12 +338,32 @@ mLexer->MustGetNext(); String varname = GetTokenString(); - // Var name must not be a number - if (varname.IsNumeric()) - Error ("variable name must not be a number"); + if (varname[0] >= '0' && varname[0] <= '9') + Error ("variable name must not start with a number"); ScriptVariable* var = DeclareGlobalVariable (type, varname); - (void) var; + + if (isconst == false) + { + var->writelevel = ScriptVariable::WRITE_Mutable; + } + else + { + mLexer->MustGetNext (tkAssign); + Expression expr (this, mLexer, type); + + if (expr.GetResult()->IsConstexpr()) + { + var->writelevel = ScriptVariable::WRITE_Constexpr; + var->value = expr.GetResult()->GetValue(); + } + else + { + // TODO: might need a VM-wise oninit for this... + Error ("const variables must be constexpr for now"); + } + } + mLexer->MustGetNext (tkSemicolon); } @@ -799,49 +816,6 @@ // ============================================================================ // -void BotscriptParser::ParseConst() -{ - ConstantInfo info; - - // Get the type - mLexer->MustGetNext(); - String typestring = GetTokenString(); - info.type = GetTypeByName (typestring); - - if (info.type == EUnknownType || info.type == EVoidType) - Error ("unknown type `%1` for constant", typestring); - - mLexer->MustGetNext(); - info.name = GetTokenString(); - - mLexer->MustGetNext (tkAssign); - - switch (info.type) - { - case EBoolType: - case EIntType: - { - mLexer->MustGetNext (tkNumber); - } break; - - case EStringType: - { - mLexer->MustGetNext (tkString); - } break; - - case EUnknownType: - case EVoidType: - break; - } - - info.val = mLexer->GetToken()->text; - mConstants << info; - - mLexer->MustGetNext (tkSemicolon); -} - -// ============================================================================ -// void BotscriptParser::ParseLabel() { CheckNotToplevel(); @@ -970,7 +944,7 @@ { DataBuffer* r = new DataBuffer (64); - if (mCurrentMode == ETopLevelMode) + if (mCurrentMode == ETopLevelMode && comm->returnvalue == EVoidType) Error ("command call at top level"); mLexer->MustGetNext (tkParenStart); @@ -1135,6 +1109,11 @@ // DataBuffer* BotscriptParser::ParseAssignment (ScriptVariable* var) { + if (var->writelevel != ScriptVariable::WRITE_Mutable) + { + Error ("cannot alter read-only variable $%1", var->name); + } + // Get an operator EAssignmentOperator oper = ParseAssignmentOperator(); DataBuffer* retbuf = new DataBuffer; @@ -1212,12 +1191,17 @@ // DataBuffer* BotscriptParser::ParseStatement() { - if (FindConstant (GetTokenString())) // There should not be constants here. - Error ("invalid use for constant\n"); + // If it's a variable, expect assignment. + if (TokenIs (tkDollarSign)) + { + mLexer->MustGetNext (tkSymbol); + ScriptVariable* var = FindGlobalVariable (GetTokenString()); - // If it's a variable, expect assignment. - if (ScriptVariable* var = FindGlobalVariable (GetTokenString())) + if (var == null) + Error ("unknown variable $%1", var->name); + return ParseAssignment (var); + } return null; } @@ -1249,17 +1233,6 @@ // ============================================================================ // -ConstantInfo* BotscriptParser::FindConstant (const String& tok) -{ - for (int i = 0; i < mConstants.Size(); i++) - if (mConstants[i].name == tok) - return &mConstants[i]; - - return null; -} - -// ============================================================================ -// bool BotscriptParser::TokenIs (EToken a) { return (mLexer->GetTokenType() == a);
--- a/src/Parser.h Sun Feb 09 14:34:13 2014 +0200 +++ b/src/Parser.h Sun Feb 09 14:56:58 2014 +0200 @@ -116,15 +116,6 @@ // ============================================================================ // -struct ConstantInfo -{ - String name; - EType type; - String val; -}; - -// ============================================================================ -// class BotscriptParser { PROPERTY (public, bool, ReadOnly, BOOL_OPS, STOCK_WRITE) @@ -138,7 +129,6 @@ BotscriptParser(); ~BotscriptParser(); - ConstantInfo* FindConstant (const String& tok); void ParseBotscript (String fileName); DataBuffer* ParseCommand (CommandInfo* comm); DataBuffer* ParseAssignment (ScriptVariable* var); @@ -192,7 +182,6 @@ DataBuffer* mIfExpression; bool mCanElse; List<UndefinedLabel> mUndefinedLabels; - List<ConstantInfo> mConstants; // How many bytes have we written to file? int mNumWrittenBytes; @@ -205,7 +194,7 @@ void ParseEventBlock(); void ParseMainloop(); void ParseOnEnterExit(); - void ParseVariableDeclaration(); + void ParseVar(); void ParseGoto(); void ParseIf(); void ParseElse(); @@ -218,7 +207,6 @@ void ParseBreak(); void ParseContinue(); void ParseBlockEnd(); - void ParseConst(); void ParseLabel(); void ParseEventdef(); void ParseFuncdef();
--- a/src/Tokens.h Sun Feb 09 14:34:13 2014 +0200 +++ b/src/Tokens.h Sun Feb 09 14:56:58 2014 +0200 @@ -104,6 +104,7 @@ tkState, tkSwitch, tkStr, + tkVar, tkVoid, tkWhile, tkTrue,
--- a/src/Variables.cc Sun Feb 09 14:34:13 2014 +0200 +++ b/src/Variables.cc Sun Feb 09 14:56:58 2014 +0200 @@ -60,7 +60,6 @@ g.index = g_GlobalVariables.Size(); g.name = name; g.statename = ""; - g.value = 0; g.type = type; g_GlobalVariables << g;
--- a/src/Variables.h Sun Feb 09 14:34:13 2014 +0200 +++ b/src/Variables.h Sun Feb 09 14:56:58 2014 +0200 @@ -31,15 +31,24 @@ #include "Main.h" +class ExpressionValue; class BotscriptParser; struct ScriptVariable { - String name; - String statename; - EType type; - int value; - int index; + enum EWritability + { + WRITE_Mutable, // normal read-many-write-many variable + WRITE_Const, // write-once const variable + WRITE_Constexpr, // const variable whose value is known to compiler + }; + + String name; + String statename; + EType type; + int index; + EWritability writelevel; + int value; inline bool IsGlobal() const {