diff --git a/apps/mwinterpreter/context.cpp b/apps/mwinterpreter/context.cpp index 618abaf83..09d70ff3e 100644 --- a/apps/mwinterpreter/context.cpp +++ b/apps/mwinterpreter/context.cpp @@ -67,6 +67,14 @@ namespace SAInterpreter mFloats.at (index) = value; } + void Context::messageBox (const std::string& message, + const std::vector& buttons) + { + std::cout << "message box: " << message << std::endl; + for (std::size_t i=0; i& buttons); + void report(); ///< Write state to std::cout }; diff --git a/components/compiler/generator.cpp b/components/compiler/generator.cpp index e704ac724..ddbae874a 100644 --- a/components/compiler/generator.cpp +++ b/components/compiler/generator.cpp @@ -150,6 +150,16 @@ namespace { code.push_back (segment5 (19)); } + + void opReturn (Compiler::Generator::CodeContainer& code) + { + code.push_back (segment5 (20)); + } + + void opMessageBox (Compiler::Generator::CodeContainer& code, int buttons) + { + code.push_back (segment3 (0, buttons)); + } } namespace Compiler @@ -321,6 +331,22 @@ namespace Compiler { opSquareRoot (code); } + + void exit (CodeContainer& code) + { + opReturn (code); + } + + void message (CodeContainer& code, Literals& literals, const std::string& message, + int buttons) + { + assert (buttons==0); + + int index = literals.addString (message); + + opPushInt (code, index); + opMessageBox (code, buttons); + } } } diff --git a/components/compiler/generator.hpp b/components/compiler/generator.hpp index 44b0fc4f2..2dd81711e 100644 --- a/components/compiler/generator.hpp +++ b/components/compiler/generator.hpp @@ -2,6 +2,7 @@ #define COMPILER_GENERATOR_H_INCLUDED #include +#include #include @@ -33,6 +34,11 @@ namespace Compiler void convert (CodeContainer& code, char fromType, char toType); void squareRoot (CodeContainer& code); + + void exit (CodeContainer& code); + + void message (CodeContainer& code, Literals& literals, const std::string& message, + int buttons); } } diff --git a/components/compiler/lineparser.cpp b/components/compiler/lineparser.cpp index 92c9aad57..09ecdb82a 100644 --- a/components/compiler/lineparser.cpp +++ b/components/compiler/lineparser.cpp @@ -76,6 +76,13 @@ namespace Compiler return false; } + if (mState==MessageState || mState==MessageCommaState) + { + Generator::message (mCode, mLiterals, name, 0); + mState = EndState; + return false; + } + return Parser::parseName (name, loc, scanner); } @@ -89,6 +96,13 @@ namespace Compiler case Scanner::K_long: mState = LongState; return true; case Scanner::K_float: mState = FloatState; return true; case Scanner::K_set: mState = SetState; return true; + case Scanner::K_messagebox: mState = MessageState; return true; + + case Scanner::K_return: + + Generator::exit (mCode); + mState = EndState; + return true; } } else if (mState==SetLocalVarState && keyword==Scanner::K_to) @@ -114,6 +128,12 @@ namespace Compiler if (code==Scanner::S_newline && mState==EndState) return false; + if (code==Scanner::S_comma && mState==MessageState) + { + mState = MessageCommaState; + return true; + } + return Parser::parseSpecial (code, loc, scanner); } diff --git a/components/compiler/lineparser.hpp b/components/compiler/lineparser.hpp index e9fae92b7..0af222d86 100644 --- a/components/compiler/lineparser.hpp +++ b/components/compiler/lineparser.hpp @@ -22,6 +22,7 @@ namespace Compiler BeginState, ShortState, LongState, FloatState, SetState, SetLocalVarState, + MessageState, MessageCommaState, EndState }; diff --git a/components/compiler/scanner.hpp b/components/compiler/scanner.hpp index 271639c97..044e02375 100644 --- a/components/compiler/scanner.hpp +++ b/components/compiler/scanner.hpp @@ -40,7 +40,7 @@ namespace Compiler K_if, K_endif, K_else, K_elseif, K_while, K_endwhile, K_return, - K_messageBox, + K_messagebox, K_set, K_to, K_getsquareroot }; diff --git a/components/interpreter/context.hpp b/components/interpreter/context.hpp index 582606c9c..32bde722e 100644 --- a/components/interpreter/context.hpp +++ b/components/interpreter/context.hpp @@ -19,7 +19,10 @@ namespace Interpreter virtual void setLocalLong (int index, int value) = 0; - virtual void setLocalFloat (int index, float value) = 0; + virtual void setLocalFloat (int index, float value) = 0; + + virtual void messageBox (const std::string& message, + const std::vector& buttons) = 0; }; } diff --git a/components/interpreter/controlopcodes.hpp b/components/interpreter/controlopcodes.hpp new file mode 100644 index 000000000..90584decb --- /dev/null +++ b/components/interpreter/controlopcodes.hpp @@ -0,0 +1,20 @@ +#ifndef INTERPRETER_CONTROLOPCODES_H_INCLUDED +#define INTERPRETER_CONTROLOPCODES_H_INCLUDED + +#include "opcodes.hpp" +#include "runtime.hpp" + +namespace Interpreter +{ + class OpReturn : public Opcode0 + { + public: + + virtual void execute (Runtime& runtime) + { + runtime.setPC (-1); + } + }; +} + +#endif diff --git a/components/interpreter/docs/vmformat.txt b/components/interpreter/docs/vmformat.txt index 748e6e3ee..c5bc133f7 100644 --- a/components/interpreter/docs/vmformat.txt +++ b/components/interpreter/docs/vmformat.txt @@ -43,7 +43,12 @@ opcodes 0-511 unused opcodes 512-1023 reserved for extensions Segment 3: -opcodes 0-511 unused +op 0: show message box with message string literal index in stack[0]; + buttons (if any) in stack[arg0]..stack[1]; + additional arguments (if any) in stack[arg0+n]..stack[arg0+1]; + n is determined according to the message string + all arguments are removed from stack +opcodes 1-511 unused opcodes 512-1023 reserved for extensions Segment 4: @@ -71,6 +76,7 @@ op 16: div (float) stack[1] by stack[0], pop twice, push result op 17: convert stack[1] from integer to float op 18: convert stack[1] from float to integer op 19: take square root of stack[0] (float) -opcodes 20-33554431 unused +op 20: return +opcodes 21-33554431 unused opcodes 33554432-67108863 reserved for extensions diff --git a/components/interpreter/installopcodes.cpp b/components/interpreter/installopcodes.cpp index b96a0a1a5..5836967ed 100644 --- a/components/interpreter/installopcodes.cpp +++ b/components/interpreter/installopcodes.cpp @@ -5,6 +5,8 @@ #include "genericopcodes.hpp" #include "localopcodes.hpp" #include "mathopcodes.hpp" +#include "controlopcodes.hpp" +#include "miscopcodes.hpp" namespace Interpreter { @@ -36,6 +38,12 @@ namespace Interpreter interpreter.installSegment5 (15, new OpDivInt); interpreter.installSegment5 (16, new OpDivInt); interpreter.installSegment5 (19, new OpSquareRoot); + + // control structures + interpreter.installSegment5 (20, new OpReturn); + + // misc + interpreter.installSegment3 (0, new OpMessageBox); } } diff --git a/components/interpreter/miscopcodes.hpp b/components/interpreter/miscopcodes.hpp new file mode 100644 index 000000000..f37620874 --- /dev/null +++ b/components/interpreter/miscopcodes.hpp @@ -0,0 +1,31 @@ +#ifndef INTERPRETER_MISCOPCODES_H_INCLUDED +#define INTERPRETER_MISCOPCODES_H_INCLUDED + +#include +#include +#include + +#include "opcodes.hpp" +#include "runtime.hpp" + +namespace Interpreter +{ + class OpMessageBox : public Opcode1 + { + public: + + virtual void execute (Runtime& runtime, unsigned int arg0) + { + if (arg0!=0) + throw std::logic_error ("message box buttons not implemented yet"); + + int index = runtime[0]; + runtime.pop(); + std::vector buttons; + runtime.getContext().messageBox (runtime.getStringLiteral (index), buttons); + } + }; +} + +#endif + diff --git a/components/interpreter/runtime.cpp b/components/interpreter/runtime.cpp index bde4d6b9f..746be60d2 100644 --- a/components/interpreter/runtime.cpp +++ b/components/interpreter/runtime.cpp @@ -3,6 +3,7 @@ #include #include +#include namespace Interpreter { @@ -30,6 +31,21 @@ namespace Interpreter return *reinterpret_cast (&literalBlock[index]); } + + std::string Runtime::getStringLiteral (int index) const + { + assert (index>=0 && index (mCode[3])); + + const char *literalBlock = + reinterpret_cast (mCode + 4 + mCode[0] + mCode[1] + mCode[2]); + + for (; index; --index) + { + literalBlock += std::strlen (literalBlock) + 1; + } + + return literalBlock; + } void Runtime::configure (const Interpreter::Type_Code *code, int codeSize) { diff --git a/components/interpreter/runtime.hpp b/components/interpreter/runtime.hpp index a683a0f0f..73e90f68a 100644 --- a/components/interpreter/runtime.hpp +++ b/components/interpreter/runtime.hpp @@ -2,6 +2,7 @@ #define INTERPRETER_RUNTIME_H_INCLUDED #include +#include #include "types.hpp" @@ -29,7 +30,9 @@ namespace Interpreter int getIntegerLiteral (int index) const; float getFloatLiteral (int index) const; - + + std::string getStringLiteral (int index) const; + void configure (const Type_Code *code, int codeSize); ///< \a context and \a code must exist as least until either configure, clear or /// the destructor is called. \a codeSize is given in 32-bit words.