From 35f71b12dc48a928d98743f607f62b2f6dbe7307 Mon Sep 17 00:00:00 2001 From: Mike Buland Date: Thu, 29 Dec 2011 23:30:49 -0700 Subject: Goto works, scopes work. --- src/enums.h | 12 ++++++++++ src/gamebuilder.cpp | 6 ++--- src/gamebuilder.h | 2 +- src/gamestate.cpp | 65 ++++++++++++++++++++++++++++++++++++++++++++--------- src/gamestate.h | 11 +++------ src/parser.y | 8 +++---- src/variable.cpp | 42 +++++++++++++++++++++++++++------- src/variable.h | 15 ++++++++++++- test.stage | 24 +++++++++++--------- 9 files changed, 139 insertions(+), 46 deletions(-) create mode 100644 src/enums.h diff --git a/src/enums.h b/src/enums.h new file mode 100644 index 0000000..2577590 --- /dev/null +++ b/src/enums.h @@ -0,0 +1,12 @@ +#ifndef ENUMS_H +#define ENUMS_H + +enum ScopeId +{ + sidLocal, + sidGlobal, + sidPlayer, + sidSituation +}; + +#endif diff --git a/src/gamebuilder.cpp b/src/gamebuilder.cpp index d1b4430..87389ff 100644 --- a/src/gamebuilder.cpp +++ b/src/gamebuilder.cpp @@ -61,7 +61,7 @@ void GameBuilder::endFunctionParams() for( Bu::StringList::iterator i = lRev.begin(); i; i++ ) { - addVarRef( *i ); + addVarRef( *i, sidLocal ); addNode( AstNode::tSwap ); addNode( AstNode::tStore ); } @@ -128,11 +128,11 @@ void GameBuilder::addLiteral( const Variable &v ) } } -void GameBuilder::addVarRef( const Bu::String &sName ) +void GameBuilder::addVarRef( const Bu::String &sName, ScopeId sid ) { if( pCurNode ) { - pCurNode->addNode( new AstLeafLiteral( AstNode::tVarName, Variable::newVariableName( sName ) ) ); + pCurNode->addNode( new AstLeafLiteral( AstNode::tVarName, Variable::newVariableName( sName, sid ) ) ); } } diff --git a/src/gamebuilder.h b/src/gamebuilder.h index e4ead71..9e40f48 100644 --- a/src/gamebuilder.h +++ b/src/gamebuilder.h @@ -31,7 +31,7 @@ public: void addNode( AstNode::Type iType ); void closeNode(); void addLiteral( const Variable &v ); - void addVarRef( const Bu::String &sName ); + void addVarRef( const Bu::String &sName, ScopeId sid ); void addFuncCall( const Bu::String &sName ); void beginGlobal(); diff --git a/src/gamestate.cpp b/src/gamestate.cpp index 14a7b53..3f09c3f 100644 --- a/src/gamestate.cpp +++ b/src/gamestate.cpp @@ -23,8 +23,10 @@ void GameState::parse( class AstBranch *pAst ) throw Bu::ExceptionBase("Nope, nothing doing, you can't parse a non-scope AstBranch."); lsLocal.push( new Scope() ); + int iDepth = lsLocal.getSize(); parse( pAst->getNodeList() ); - delete lsLocal.peekPop(); + if( lsLocal.getSize() == iDepth ) + delete lsLocal.peekPop(); } void GameState::init() @@ -38,6 +40,11 @@ void GameState::init() void GameState::gotoSituation( const Bu::String &sName ) { + lStack.clear(); + for( ScopeList::iterator i = lsLocal.begin(); i; i++ ) + delete *i; + lsLocal.clear(); + Situation *pSit = pGame->getSituation( sName ); sCurSituation = sName; if( !hsSituation.has( sName ) ) @@ -46,18 +53,22 @@ void GameState::gotoSituation( const Bu::String &sName ) pSit->exec( *this, Situation::modeSetup ); } + // This is here in case you use a goto in a setup mode + if( bEscape ) + return; + pSit->exec( *this, Situation::modeEnter ); } void GameState::callFunction( const Bu::String &sName ) { - lsLocal.push( new Scope() ); pGame->getFunction( sName )->call( *this ); - delete lsLocal.peekPop(); } Variable GameState::getVariable( const Bu::String &sName, ScopeId id ) { + try + { switch( id ) { case sidLocal: @@ -72,6 +83,13 @@ Variable GameState::getVariable( const Bu::String &sName, ScopeId id ) case sidSituation: return hsSituation.get( sCurSituation )->get( sName ); } + } + catch( Bu::HashException &e ) + { + throw Bu::ExceptionBase("No %d variable named %s found.", + id, + sName.getStr() ); + } throw Bu::ExceptionBase("Really bad scopeid passed into getVariable"); } @@ -104,7 +122,10 @@ void GameState::setVariable( const Bu::String &sName, const Variable &v, Variable GameState::deref( const Variable &src ) { if( src.getType() == Variable::tVariable ) - return getVariable( src.getString() ); + { + VariableRef r = src.getVariableRef(); + return getVariable( r.sName, r.sid ); + } return src; } @@ -112,12 +133,16 @@ Variable GameState::popDeref() { Variable v = lStack.peekPop(); if( v.getType() == Variable::tVariable ) - return getVariable( v.getString() ); + { + VariableRef r = v.getVariableRef(); + return getVariable( r.sName, r.sid ); + } return v; } void GameState::parse( const AstBranch::NodeList &lCode ) { + bEscape = false; for( AstBranch::NodeList::const_iterator i = lCode.begin(); i; i++ ) { // sio << "Stack: " << lStack << sio.nl; @@ -176,7 +201,8 @@ void GameState::parse( const AstBranch::NodeList &lCode ) { Variable y = popDeref(); Variable dst = pop(); - setVariable( dst.getString(), y ); + VariableRef r = dst.getVariableRef(); + setVariable( r.sName, y, r.sid ); } break; @@ -242,7 +268,8 @@ void GameState::parse( const AstBranch::NodeList &lCode ) { Variable y = popDeref(); Variable x = pop(); - setVariable( x.getString(), getVariable( x.getString() ) + y ); + VariableRef r = x.getVariableRef(); + setVariable( r.sName, getVariable( r.sName, r.sid ) + y, r.sid ); } break; @@ -250,7 +277,8 @@ void GameState::parse( const AstBranch::NodeList &lCode ) { Variable y = popDeref(); Variable x = pop(); - setVariable( x.getString(), getVariable( x.getString() ) - y ); + VariableRef r = x.getVariableRef(); + setVariable( r.sName, getVariable( r.sName, r.sid ) - y, r.sid ); } break; @@ -258,7 +286,8 @@ void GameState::parse( const AstBranch::NodeList &lCode ) { Variable y = popDeref(); Variable x = pop(); - setVariable( x.getString(), getVariable( x.getString() ) / y ); + VariableRef r = x.getVariableRef(); + setVariable( r.sName, getVariable( r.sName, r.sid ) / y, r.sid ); } break; @@ -266,7 +295,8 @@ void GameState::parse( const AstBranch::NodeList &lCode ) { Variable y = popDeref(); Variable x = pop(); - setVariable( x.getString(), getVariable( x.getString() ) * y ); + VariableRef r = x.getVariableRef(); + setVariable( r.sName, getVariable( r.sName, r.sid ) * y, r.sid ); } break; @@ -276,6 +306,16 @@ void GameState::parse( const AstBranch::NodeList &lCode ) case AstNode::tIn: case AstNode::tGoto: + { + Variable x = popDeref(); + if( x.getType() != Variable::tSituation ) + throw Bu::ExceptionBase("You cannot goto anything but a situation."); + gotoSituation( x.getString() ); + bEscape = true; + return; + } + break; + case AstNode::tSwap: { Variable y = pop(); @@ -329,6 +369,11 @@ void GameState::parse( const AstBranch::NodeList &lCode ) case AstNode::tWhile: break; } + + if( bEscape ) + { + return; + } } } diff --git a/src/gamestate.h b/src/gamestate.h index 83d8594..6000419 100644 --- a/src/gamestate.h +++ b/src/gamestate.h @@ -4,6 +4,7 @@ #include "astbranch.h" #include "variable.h" #include "scope.h" +#include "enums.h" class Game; @@ -25,14 +26,6 @@ public: void callFunction( const Bu::String &sName ); - enum ScopeId - { - sidLocal, - sidGlobal, - sidPlayer, - sidSituation - }; - Variable getVariable( const Bu::String &sName, ScopeId id=sidLocal ); void setVariable( const Bu::String &sName, const Variable &v, ScopeId id=sidLocal ); @@ -51,6 +44,8 @@ private: ScopeHash hsSituation; Bu::String sCurSituation; + bool bEscape; + VariableList lStack; }; diff --git a/src/parser.y b/src/parser.y index ccb0c97..484fd25 100644 --- a/src/parser.y +++ b/src/parser.y @@ -188,10 +188,10 @@ ifnext: | tokElse { bld.addNode( AstNode::tScope ); } ifbase ; -varRef: tokIdent { bld.addVarRef( *($1) ); } - | tokPlayer '.' tokIdent - | tokGlobal '.' tokIdent - | tokSituation '.' tokIdent +varRef: tokIdent { bld.addVarRef( *($1), sidLocal ); } + | tokPlayer '.' tokIdent { bld.addVarRef( *($3), sidPlayer ); } + | tokGlobal '.' tokIdent { bld.addVarRef( *($3), sidGlobal ); } + | tokSituation '.' tokIdent { bld.addVarRef( *($3), sidSituation ); } ; literal: tokInt { bld.addLiteral( Variable( $1 ) ); } diff --git a/src/variable.cpp b/src/variable.cpp index 5e2462c..4c5ca4c 100644 --- a/src/variable.cpp +++ b/src/variable.cpp @@ -4,6 +4,11 @@ #include typedef Bu::ExceptionBase VariableException; + +bool VariableRef::operator==( const VariableRef &rhs ) const +{ + return sid == rhs.sid && sName == rhs.sName; +} Variable::Variable() : eType( tNull ), @@ -62,10 +67,11 @@ Variable Variable::newSituationName( const Bu::String &s ) return v; } -Variable Variable::newVariableName( const Bu::String &s ) +Variable Variable::newVariableName( const Bu::String &s, ScopeId sid ) { Variable v( tVariable ); - (*v.sValue) = s; + v.rValue->sName = s; + v.rValue->sid = sid; return v; } @@ -86,9 +92,16 @@ double Variable::getFloat() const Bu::String Variable::getString() const { + if( eType != tString && eType != tSituation ) + throw Bu::ExceptionBase("That's not a string."); return *sValue; } +VariableRef Variable::getVariableRef() const +{ + return *rValue; +} + Variable Variable::to( Type e ) const { if( e == eType ) @@ -222,10 +235,13 @@ Variable &Variable::operator=( const Variable &rhs ) case tString: case tSituation: - case tVariable: (*sValue) = *rhs.sValue; break; + case tVariable: + (*rValue) = *rhs.rValue; + break; + case tList: (*lValue) = *rhs.lValue; break; @@ -527,8 +543,10 @@ bool Variable::operator==( const Variable &rhs ) const case tString: case tSituation: - case tVariable: return (*sValue) == (*rhs.sValue); + + case tVariable: + return (*rValue) == (*rhs.rValue); case tList: return (*lValue) == (*rhs.lValue); @@ -678,9 +696,12 @@ void Variable::initType() { case tString: case tSituation: - case tVariable: sValue = new Bu::String(); break; + + case tVariable: + rValue = new VariableRef(); + break; case tList: lValue = new VList(); @@ -698,9 +719,12 @@ void Variable::deinitType() { case tString: case tSituation: - case tVariable: delete sValue; break; + + case tVariable: + delete rValue; + break; case tList: delete lValue; @@ -729,8 +753,10 @@ template<> uint32_t Bu::__calcHashCode( const Variable &k ) case Variable::tString: case Variable::tSituation: - case Variable::tVariable: return Bu::__calcHashCode( *k.sValue ); + + case Variable::tVariable: + throw VariableException("You cannot use a variable ref as a key in a dictionary."); case Variable::tList: throw VariableException("You cannot use a list as a key in a dictionary."); @@ -767,7 +793,7 @@ Bu::Formatter &operator<<( Bu::Formatter &f, const Variable &v ) return f << "<<" << *v.sValue << ">>"; case Variable::tVariable: - return f << "(varref:\"" << *v.sValue << "\")"; + return f << "(varref:\"" << v.rValue->sName << "\")"; case Variable::tList: return f << *v.lValue; diff --git a/src/variable.h b/src/variable.h index 42dd865..7f482a3 100644 --- a/src/variable.h +++ b/src/variable.h @@ -6,6 +6,17 @@ #include #include +#include "enums.h" + +class VariableRef +{ +public: + ScopeId sid; + Bu::String sName; + + bool operator==( const VariableRef &rhs ) const; +}; + class Variable { friend uint32_t Bu::__calcHashCode( const Variable &k ); @@ -35,7 +46,7 @@ public: virtual ~Variable(); static Variable newSituationName( const Bu::String &s ); - static Variable newVariableName( const Bu::String &s ); + static Variable newVariableName( const Bu::String &s, ScopeId sid ); Type getType() const { return eType; } @@ -43,6 +54,7 @@ public: int64_t getInt() const; double getFloat() const; Bu::String getString() const; + VariableRef getVariableRef() const; Variable to( Type e ) const; @@ -81,6 +93,7 @@ private: Bu::String *sValue; VList *lValue; VHash *hValue; + VariableRef *rValue; }; }; diff --git a/test.stage b/test.stage index f150baa..c19dac9 100644 --- a/test.stage +++ b/test.stage @@ -26,22 +26,24 @@ function sillyDisplay( txt, extra ) } } +function myGoto( txt ) +{ + display( txt ); + goto( txt ); +} + situation <> { setup { - name = "Bob"; + player.name = "Bob"; + name = player.name + "o"; name += " The Man"; display("This is the setup phase for start, " + name); - display( 5 <= 1 ); - display( 1 <= 1 ); - display( 0 <= 1 ); - sillyDisplay( "Hello", true ); - - if name == "Bob The Man" then - { - display("You are bob"); - } + sillyDisplay( "Hello", name == player.name ); + + myGoto( <> ); + display("You shouldn't see this."); } enter @@ -54,6 +56,6 @@ situation <> { enter { - display('''Entered stuff'''); + display('''Entered stuff''' + player.name); } } -- cgit v1.2.3