From f66458278ce3663397fc985a1253c85b74f011e6 Mon Sep 17 00:00:00 2001 From: Mike Buland Date: Thu, 29 Dec 2011 22:27:59 -0700 Subject: Most AstNodes work now. Next up: loops, proper variable references with scopes, and gotos. --- src/astfunction.cpp | 3 ++ src/astfunction.h | 1 + src/astnode.cpp | 1 + src/astnode.h | 1 + src/gamebuilder.cpp | 17 +++++++ src/gamebuilder.h | 1 + src/gamestate.cpp | 72 ++++++++++++++++++++++++++++ src/main.cpp | 3 -- src/parser.y | 2 +- src/variable.cpp | 134 +++++++++++++++++++++++++++++++++++++++++++++++++--- test.stage | 23 ++++++--- 11 files changed, 242 insertions(+), 16 deletions(-) diff --git a/src/astfunction.cpp b/src/astfunction.cpp index f091644..f5e25dc 100644 --- a/src/astfunction.cpp +++ b/src/astfunction.cpp @@ -1,6 +1,8 @@ #include "astfunction.h" #include "astbranch.h" +#include "gamestate.h" + AstFunction::AstFunction( const Bu::String &sName ) : sName( sName ), pAst( NULL ) @@ -14,6 +16,7 @@ AstFunction::~AstFunction() Variable AstFunction::call( class GameState &gState ) { + gState.parse( pAst ); } void AstFunction::addParam( const Bu::String &sName ) diff --git a/src/astfunction.h b/src/astfunction.h index 4b2a049..a546b19 100644 --- a/src/astfunction.h +++ b/src/astfunction.h @@ -13,6 +13,7 @@ public: virtual Variable call( class GameState &gState ); void addParam( const Bu::String &sName ); + const Bu::StringList &getParamList() { return lParam; } void setAst( class AstBranch *pAst ); private: diff --git a/src/astnode.cpp b/src/astnode.cpp index d7295b3..88363c9 100644 --- a/src/astnode.cpp +++ b/src/astnode.cpp @@ -40,6 +40,7 @@ Bu::Formatter &operator<<( Bu::Formatter &f, AstNode::Type t ) case AstNode::tNegate: return f << "tNegate"; case AstNode::tIn: return f << "tIn"; case AstNode::tGoto: return f << "tGoto"; + case AstNode::tSwap: return f << "tSwap"; case AstNode::tLeafLiteral: return f << "!tLeafLiteral!"; case AstNode::tVarName: return f << "tVarName"; diff --git a/src/astnode.h b/src/astnode.h index c0a8eea..63bf64f 100644 --- a/src/astnode.h +++ b/src/astnode.h @@ -30,6 +30,7 @@ public: tNegate = 0x01000012, tIn = 0x01000013, tGoto = 0x01000014, + tSwap = 0x01000015, tLeafLiteral = 0x02000000, tVarName = 0x02000001, diff --git a/src/gamebuilder.cpp b/src/gamebuilder.cpp index 6c42fb0..d1b4430 100644 --- a/src/gamebuilder.cpp +++ b/src/gamebuilder.cpp @@ -50,6 +50,23 @@ void GameBuilder::addFunctionParam( const Bu::String &sName ) sio << " - Param added '" << sName << "'" << sio.nl; } +void GameBuilder::endFunctionParams() +{ + Bu::StringList lRev; + for( Bu::StringList::const_iterator i = pCurFnc->getParamList().begin(); + i; i++ ) + { + lRev.prepend( *i ); + } + + for( Bu::StringList::iterator i = lRev.begin(); i; i++ ) + { + addVarRef( *i ); + addNode( AstNode::tSwap ); + addNode( AstNode::tStore ); + } +} + void GameBuilder::endFunction() { sio << "Function ended: " << *pCurRoot << sio.nl; diff --git a/src/gamebuilder.h b/src/gamebuilder.h index 50dcbb7..e4ead71 100644 --- a/src/gamebuilder.h +++ b/src/gamebuilder.h @@ -20,6 +20,7 @@ public: void beginFunction( const Bu::String &sName ); void addFunctionParam( const Bu::String &sName ); + void endFunctionParams(); void endFunction(); void beginSituation( const Bu::String &sName ); diff --git a/src/gamestate.cpp b/src/gamestate.cpp index 5577c17..14a7b53 100644 --- a/src/gamestate.cpp +++ b/src/gamestate.cpp @@ -51,7 +51,9 @@ void GameState::gotoSituation( const Bu::String &sName ) 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 ) @@ -119,10 +121,19 @@ void GameState::parse( const AstBranch::NodeList &lCode ) for( AstBranch::NodeList::const_iterator i = lCode.begin(); i; i++ ) { // sio << "Stack: " << lStack << sio.nl; +// sio << "exec: " << (*i)->getType() << sio.nl; switch( (*i)->getType() ) { // tLeaf case AstNode::tNot: + { + Variable x = popDeref(); + if( x.getType() != Variable::tBool ) + throw Bu::ExceptionBase("Non-bool used with logical not operator."); + push( Variable( !x.getBool() ) ); + } + break; + case AstNode::tComp: { push( popDeref() == popDeref() ); @@ -130,9 +141,37 @@ void GameState::parse( const AstBranch::NodeList &lCode ) break; case AstNode::tCompGt: + { + Variable y = popDeref(); + Variable x = popDeref(); + push( x > y ); + } + break; + case AstNode::tCompLt: + { + Variable y = popDeref(); + Variable x = popDeref(); + push( x < y ); + } + break; + case AstNode::tCompGtEq: + { + Variable y = popDeref(); + Variable x = popDeref(); + push( x >= y ); + } + break; + case AstNode::tCompLtEq: + { + Variable y = popDeref(); + Variable x = popDeref(); + push( x <= y ); + } + break; + case AstNode::tStore: { Variable y = popDeref(); @@ -142,7 +181,31 @@ void GameState::parse( const AstBranch::NodeList &lCode ) break; case AstNode::tAnd: + { + Variable y = popDeref(); + Variable x = popDeref(); + if( x.getType() != Variable::tBool || + y.getType() != Variable::tBool ) + { + throw Bu::ExceptionBase("Non-bool used in logical AND operator."); + } + lStack.push( Variable( x.getBool() && y.getBool() ) ); + } + break; + case AstNode::tOr: + { + Variable y = popDeref(); + Variable x = popDeref(); + if( x.getType() != Variable::tBool || + y.getType() != Variable::tBool ) + { + throw Bu::ExceptionBase("Non-bool used in logical OR operator."); + } + lStack.push( Variable( x.getBool() || y.getBool() ) ); + } + break; + case AstNode::tPlus: { Variable y = popDeref(); @@ -212,6 +275,15 @@ void GameState::parse( const AstBranch::NodeList &lCode ) break; case AstNode::tIn: + case AstNode::tGoto: + case AstNode::tSwap: + { + Variable y = pop(); + Variable x = pop(); + push( y ); + push( x ); + } + break; // tLeafLiteral case AstNode::tVarName: diff --git a/src/main.cpp b/src/main.cpp index 273158b..8fe5247 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -30,9 +30,6 @@ int main( int argc, char *argv[] ) GameState gs( pGame ); gs.init(); - gs.gotoSituation("stuff"); - gs.gotoSituation("start"); - return 0; } diff --git a/src/parser.y b/src/parser.y index ffb6da2..ccb0c97 100644 --- a/src/parser.y +++ b/src/parser.y @@ -134,7 +134,7 @@ situationMode: tokSetup { bld.beginSituationMode( Situation::modeSetup ); } | tokEnter { bld.beginSituationMode( Situation::modeEnter ); } ; -function: tokFunction tokIdent { bld.beginFunction( *($2) ); } '(' funcParamList ')' '{' cmpltExprList '}' { bld.endFunction(); } +function: tokFunction tokIdent { bld.beginFunction( *($2) ); } '(' funcParamList ')' { bld.endFunctionParams(); } '{' cmpltExprList '}' { bld.endFunction(); } ; funcParamList: diff --git a/src/variable.cpp b/src/variable.cpp index d5bde2e..5e2462c 100644 --- a/src/variable.cpp +++ b/src/variable.cpp @@ -543,12 +543,134 @@ bool Variable::operator!=( const Variable &rhs ) const return !(*this == rhs); } -/* -Variable &Variable::operator>( const Variable &rhs ); -Variable &Variable::operator<( const Variable &rhs ); -Variable &Variable::operator>=( const Variable &rhs ); -Variable &Variable::operator<=( const Variable &rhs ); -*/ +bool Variable::operator>( const Variable &rhs ) const +{ + if( eType != rhs.eType ) + return false; + + switch( eType ) + { + case tNull: + throw Bu::ExceptionBase("You cannot use > to compare nulls."); + + case tBool: + throw Bu::ExceptionBase("You cannot use > to compare bools."); + + case tInt: + return iValue > rhs.iValue; + + case tFloat: + return fValue > rhs.fValue; + + case tString: + case tSituation: + case tVariable: + throw Bu::ExceptionBase("You cannot use > to compare strings."); + + case tList: + throw Bu::ExceptionBase("You cannot use > to compare lists."); + + case tDictionary: + throw Bu::ExceptionBase("You cannot use > to compare dictionary."); + } +} + +bool Variable::operator<( const Variable &rhs ) const +{ + if( eType != rhs.eType ) + return false; + + switch( eType ) + { + case tNull: + throw Bu::ExceptionBase("You cannot use < to compare nulls."); + + case tBool: + throw Bu::ExceptionBase("You cannot use < to compare bools."); + + case tInt: + return iValue < rhs.iValue; + + case tFloat: + return fValue < rhs.fValue; + + case tString: + case tSituation: + case tVariable: + throw Bu::ExceptionBase("You cannot use < to compare strings."); + + case tList: + throw Bu::ExceptionBase("You cannot use < to compare lists."); + + case tDictionary: + throw Bu::ExceptionBase("You cannot use < to compare dictionary."); + } +} + +bool Variable::operator>=( const Variable &rhs ) const +{ + if( eType != rhs.eType ) + return false; + + switch( eType ) + { + case tNull: + throw Bu::ExceptionBase("You cannot use >= to compare nulls."); + + case tBool: + throw Bu::ExceptionBase("You cannot use >= to compare bools."); + + case tInt: + return iValue >= rhs.iValue; + + case tFloat: + return fValue >= rhs.fValue; + + case tString: + case tSituation: + case tVariable: + throw Bu::ExceptionBase("You cannot use >= to compare strings."); + + case tList: + throw Bu::ExceptionBase("You cannot use >= to compare lists."); + + case tDictionary: + throw Bu::ExceptionBase("You cannot use >= to compare dictionary."); + } +} + +bool Variable::operator<=( const Variable &rhs ) const +{ + if( eType != rhs.eType ) + return false; + + switch( eType ) + { + case tNull: + throw Bu::ExceptionBase("You cannot use <= to compare nulls."); + + case tBool: + throw Bu::ExceptionBase("You cannot use <= to compare bools."); + + case tInt: + return iValue <= rhs.iValue; + + case tFloat: + return fValue <= rhs.fValue; + + case tString: + case tSituation: + case tVariable: + throw Bu::ExceptionBase("You cannot use <= to compare strings."); + + case tList: + throw Bu::ExceptionBase("You cannot use <= to compare lists."); + + case tDictionary: + throw Bu::ExceptionBase("You cannot use <= to compare dictionary."); + } +} + void Variable::initType() { iValue = 0; diff --git a/test.stage b/test.stage index 75bff27..f150baa 100644 --- a/test.stage +++ b/test.stage @@ -13,6 +13,19 @@ global } } +function sillyDisplay( txt, extra ) +{ + display("!~! " + txt + " !~!"); + if extra then + { + display("And then some extra!"); + } + else + { + display("...no extra for you"); + } +} + situation <> { setup @@ -20,17 +33,15 @@ situation <> name = "Bob"; name += " The Man"; display("This is the setup phase for start, " + name); - display( 5 == 6 ); - display( 5 == 5 ); + display( 5 <= 1 ); + display( 1 <= 1 ); + display( 0 <= 1 ); + sillyDisplay( "Hello", true ); if name == "Bob The Man" then { display("You are bob"); } - else - { - display("You are not bob"); - } } enter -- cgit v1.2.3