aboutsummaryrefslogtreecommitdiffstats
path: root/runner.h
diff options
context:
space:
mode:
Diffstat (limited to 'runner.h')
-rw-r--r--runner.h658
1 files changed, 658 insertions, 0 deletions
diff --git a/runner.h b/runner.h
new file mode 100644
index 0000000..e1faeda
--- /dev/null
+++ b/runner.h
@@ -0,0 +1,658 @@
+#ifndef INCLUDE_BLASSIC_RUNNER_H
+#define INCLUDE_BLASSIC_RUNNER_H
+
+// runner.h
+// Revision 6-feb-2005
+
+//#include "program.h"
+
+class Program;
+
+#include "blassic.h"
+
+#include "error.h"
+#include "file.h"
+#include "codeline.h"
+#include "var.h"
+#include "element.h"
+
+//#include "runnerline.h"
+
+#include <iostream>
+#include <stack>
+#include <vector>
+#include <map>
+
+
+// ********************* GlobalRunner **********************
+
+
+namespace blassic {
+
+
+namespace onbreak {
+
+enum BreakState { BreakStop, BreakCont, BreakGosub };
+
+} // namespace onbreak
+
+
+} // namespace blassic
+
+
+enum TrigonometricMode { TrigonometricRad, TrigonometricDeg };
+
+// We encapsulate the random generator in a class to have all code
+// related to it in a place, and to be able to change it easily.
+
+// random in some systems may not use the RAND_MAX value,
+// then we use it only in linux.
+
+class RandomGenerator {
+public:
+ BlNumber operator () ()
+ {
+ #if defined __linux__
+ return BlNumber (random () ) / (RAND_MAX + 1.0);
+ #else
+ return BlNumber (rand () ) / (RAND_MAX + 1.0);
+ #endif
+ }
+ void seed (unsigned int value)
+ {
+ #if defined __linux__
+ srandom (value);
+ #else
+ srand (value);
+ #endif
+ }
+};
+
+class GlobalRunner {
+public:
+ GlobalRunner (Program & prog);
+ ~GlobalRunner ();
+
+ // Program
+private:
+ Program & program;
+public:
+ Program & getprogram () { return program; }
+
+ // TRON stuff
+private:
+ bool fTron, fTronLine;
+ BlChannel blcTron;
+ void do_tronline (const CodeLine & line);
+public:
+ void tron (bool fLine, BlChannel blc);
+ void troff ();
+ void tronline (const CodeLine & codeline)
+ {
+ if (fTron)
+ do_tronline (codeline);
+ }
+
+ // GlobalRunner Channel stuff
+public:
+ typedef std::map <BlChannel, blassic::file::BlFile *> ChanFile;
+ typedef std::map <BlChannel, BlLineNumber> ChanPolled;
+private:
+ ChanFile chanfile;
+ ChanPolled chanpolled;
+ bool alreadypolled;
+ bool clearingpolled;
+public:
+ bool assign_channel_var
+ (const std::string & var, const Dimension & dim,
+ const std::string & value,
+ blassic::file::BlFile::Align align);
+ bool assign_mid_channel_var
+ (const std::string & var, const Dimension & dim,
+ const std::string & value,
+ size_t inipos, std::string::size_type len);
+ bool isfileopen (BlChannel channel) const
+ { return chanfile.find (channel) != chanfile.end (); }
+ BlChannel freefile () const;
+ blassic::file::BlFile & getfile (BlChannel channel) const;
+ void setfile (BlChannel channel, blassic::file::BlFile * npfile);
+ void resetfile0 ();
+ void resetfileprinter ();
+ void close_all ();
+ void destroy_windows ();
+ void closechannel (BlChannel channel);
+ void windowswap (BlChannel ch1, BlChannel ch2);
+
+ void pollchannel (BlChannel ch, BlLineNumber line);
+ bool channelspolled ();
+ BlLineNumber getpollnumber ();
+ void setpolled ();
+ void clearpolled ();
+
+ // GlobalRunner DATA / READ / RESTORE stuff
+private:
+ BlLineNumber datanumline;
+ BlChunk datachunk;
+ unsigned short dataelem;
+public:
+ BlLineNumber & getdatanumline () { return datanumline; }
+ BlChunk & getdatachunk () { return datachunk; }
+ unsigned short & getdataelem () { return dataelem; }
+ void setreadline (BlLineNumber bln)
+ {
+ datanumline= bln;
+ datachunk= 0;
+ dataelem= 0;
+ }
+ void clearreadline ()
+ {
+ datanumline= LineBeginProgram;
+ datachunk= 0;
+ dataelem= 0;
+ }
+
+ // GlobalRunner ON ERROR GOTO stuff.
+private:
+ BlLineNumber blnErrorGoto;
+ BlLineNumber blnErrorGotoSource;
+public:
+ void clearerrorgoto ();
+ void seterrorgoto (BlLineNumber line, BlLineNumber source);
+ BlLineNumber geterrorgoto () const
+ { return blnErrorGoto; }
+ BlLineNumber geterrorgotosource () const
+ { return blnErrorGotoSource; }
+
+ // GlobalRunner ON BREAK
+private:
+ blassic::onbreak::BreakState breakstate;
+ BlLineNumber breakgosubline;
+public:
+ void setbreakstate (blassic::onbreak::BreakState newstate)
+ {
+ breakstate= newstate;
+ }
+ blassic::onbreak::BreakState getbreakstate () const
+ { return breakstate; }
+ void setbreakgosub (BlLineNumber bln)
+ {
+ breakstate= blassic::onbreak::BreakGosub;
+ breakgosubline= bln;
+ }
+ BlLineNumber getbreakgosub () { return breakgosubline; }
+
+ // Control of depth of fn calls.
+private:
+ size_t fn_current_level;
+public:
+ size_t fn_level () const { return fn_current_level; }
+ void inc_fn_level ();
+ void dec_fn_level ();
+
+ // Trigonometric mode.
+private:
+ TrigonometricMode trigmode;
+public:
+ TrigonometricMode trigonometric_mode () const { return trigmode; }
+ void trigonometric_default () { trigmode= TrigonometricRad; }
+ void trigonometric_mode (TrigonometricMode trigmode_n)
+ { trigmode= trigmode_n; }
+
+ // Random number generator.
+private:
+ RandomGenerator randgen;
+public:
+ BlNumber getrandom () { return randgen (); }
+ void seedrandom (unsigned int value) { randgen.seed (value); }
+};
+
+
+// ********************* Runner **********************
+
+
+class GosubStack {
+private:
+ GlobalRunner & globalrunner;
+ typedef std::stack <GosubElement> st_t;
+ st_t st;
+public:
+ typedef st_t::size_type size_type;
+public:
+ GosubStack (GlobalRunner & globalrunner);
+ ~GosubStack ();
+ bool empty () const
+ {
+ return st.empty ();
+ }
+ size_type size () const
+ {
+ return st.size ();
+ }
+ void check_fn () const
+ {
+ if (st.empty () )
+ throw ErrUnexpectedFnEnd;
+ if (st.top ().isgosub () )
+ throw ErrGosubWithoutReturn;
+ }
+ void erase ();
+ void push (ProgramPos pos, bool is_polled)
+ {
+ st.push (GosubElement (pos, is_polled) );
+ if (is_polled)
+ globalrunner.setpolled ();
+ }
+ void push (LocalLevel & ll)
+ {
+ st.push (GosubElement (ll) );
+ }
+ void pop (ProgramPos & ppos)
+ {
+ if (st.empty () )
+ throw ErrReturnWithoutGosub;
+ GosubElement & go= st.top ();
+ if (! go.isgosub () )
+ throw ErrReturnWithoutGosub;
+ ppos= go.getpos ();
+ go.freelocalvars ();
+ if (go.ispolled () )
+ globalrunner.clearpolled ();
+ st.pop ();
+ }
+ void popfn ()
+ {
+ if (st.empty () )
+ throw ErrReturnWithoutGosub;
+ GosubElement & go= st.top ();
+ if (go.isgosub () )
+ throw ErrGosubWithoutReturn;
+ go.freelocalvars ();
+ st.pop ();
+ }
+ void addlocalvar (const std::string & name)
+ {
+ if (st.empty () )
+ throw ErrMisplacedLocal;
+ GosubElement go= st.top ();
+ go.addlocalvar (name);
+ }
+};
+
+class Runner {
+public:
+ enum RunnerStatus {
+ Ended,
+ FnEnded,
+ ReadyToRun,
+ Running,
+ Stopped,
+ Jump,
+ Goto,
+ //InitingCommand,
+ //Command,
+ JumpResumeNext,
+ LastStatus= JumpResumeNext,
+ };
+private:
+ enum StatusRun { KeepRunning, StopNow };
+
+ typedef StatusRun (Runner::* checkstatusfunc)
+ (CodeLine &, const CodeLine &);
+ static checkstatusfunc checkstatus [LastStatus + 1];
+
+ StatusRun checkstatusEnded
+ (CodeLine & line, const CodeLine & line0);
+ StatusRun checkstatusFnEnded
+ (CodeLine & line, const CodeLine & line0);
+ StatusRun checkstatusReadyToRun
+ (CodeLine & line, const CodeLine & line0);
+ StatusRun checkstatusRunning
+ (CodeLine & line, const CodeLine & line0);
+ StatusRun checkstatusStopped
+ (CodeLine & line, const CodeLine & line0);
+ StatusRun checkstatusJump
+ (CodeLine & line, const CodeLine & line0);
+ StatusRun checkstatusGoto
+ (CodeLine & line, const CodeLine & line0);
+ //StatusRun checkstatusInitingCommand
+ // (CodeLine & line, const CodeLine & line0);
+ //StatusRun checkstatusCommand
+ // (CodeLine & line, const CodeLine & line0);
+ StatusRun checkstatusJumpResumeNext
+ (CodeLine & line, const CodeLine & line0);
+ bool is_run_status (CodeLine & line, const CodeLine & line0);
+
+
+ GlobalRunner & globalrunner;
+ Program & program;
+ RunnerStatus status;
+ bool fInElse;
+ bool fInWend;
+public:
+ //Runner (Program & prog);
+ Runner (GlobalRunner & gr);
+ Runner (const Runner & runner);
+ ~Runner ();
+
+ Program & getprogram () { return program; }
+ void clear ();
+ void getline (std::string & line);
+ void runline_catch (const CodeLine & codeline, ProgramPos pos,
+ BlError & berr, bool & endloop, bool & dobreak);
+ void runline (const CodeLine & codeline0);
+ void run ();
+ bool editline (BlLineNumber bln, std::string & str);
+ void interactive ();
+
+ // Runner *********** Errors **************
+private:
+ BlCode codprev;
+ BlError berrLast;
+public:
+ BlErrNo geterr () const;
+ ProgramPos geterrpos () const;
+ BlLineNumber geterrline () const;
+ void clearerror ();
+ BlError geterror () const;
+ void seterror (const BlError & er);
+
+ // Runner *********** Flow control **************
+private:
+ ProgramPos posgoto;
+public:
+ void setstatus (RunnerStatus stat) { status= stat; }
+ void run_to (BlLineNumber line)
+ {
+ posgoto= line;
+ status= ReadyToRun;
+ }
+ void run_to (ProgramPos pos)
+ {
+ posgoto= pos;
+ status= ReadyToRun;
+ }
+ void jump_to (BlLineNumber line)
+ {
+ posgoto= line;
+ status= Jump;
+ }
+ void jump_to (ProgramPos pos)
+ {
+ posgoto= pos;
+ status= Jump;
+ }
+ void goto_to (BlLineNumber line)
+ {
+ posgoto= line;
+ status= Goto;
+ }
+ void goto_to (ProgramPos pos)
+ {
+ posgoto= pos;
+ status= Goto;
+ }
+ void resume_next (ProgramPos pos)
+ {
+ posgoto= pos;
+ status= JumpResumeNext;
+ }
+
+ // Runner *********** FOR / NEXT **************
+private:
+ std::stack <ForElement *, std::vector <ForElement *> > forstack;
+public:
+ void push_for (ForElement * pfe)
+ {
+ forstack.push (pfe);
+ }
+ //bool for_empty () const { return forstack.empty (); }
+ ForElement & for_top ()
+ {
+ if (forstack.empty () )
+ throw ErrNextWithoutFor;
+ return * forstack.top ();
+ }
+ void for_pop () { delete forstack.top (); forstack.pop (); }
+ // New version, supposed faster.
+ bool next ();
+ bool next (const std::string & varname);
+
+ // Runner *********** GOSUB / RETURN / FN **************
+private:
+ GosubStack gosubstack;
+public:
+ bool gosub_empty () const
+ { return gosubstack.empty (); }
+ size_t gosub_size () const
+ { return gosubstack.size (); }
+ void gosub_check_fn () const
+ { gosubstack.check_fn (); }
+ void gosub_pop (ProgramPos & pos)
+ { gosubstack.pop (pos); }
+ void fn_pop () { gosubstack.popfn (); }
+ void gosub_addlocalvar (const std::string & str)
+ {
+ gosubstack.addlocalvar (str);
+ }
+ void gosub_push (LocalLevel & ll)
+ {
+ gosubstack.push (ll);
+ }
+ void gosub_line (BlLineNumber dest, ProgramPos posgosub,
+ bool is_polled= false)
+ {
+ gosubstack.push (posgosub, is_polled);
+ goto_to (dest);
+ }
+ size_t fn_level () const { return globalrunner.fn_level (); }
+ void inc_fn_level ()
+ { globalrunner.inc_fn_level (); }
+ void dec_fn_level ()
+ { globalrunner.dec_fn_level (); }
+
+ // Runner *********** REPEAT / UNTIL **************
+private:
+ std::stack <RepeatElement> repeatstack;
+public:
+ bool repeat_empty () const { return repeatstack.empty (); }
+ void repeat_pop () { repeatstack.pop (); }
+ RepeatElement & repeat_top () { return repeatstack.top (); }
+ void repeat_push (const RepeatElement & re) { repeatstack.push (re); }
+
+ // Runner *********** WHILE / WEND **************
+private:
+ std::stack <WhileElement> whilestack;
+public:
+ bool in_wend () { return fInWend; }
+ void in_wend (bool f) { fInWend= f; }
+ bool while_empty () { return whilestack.empty (); }
+ void while_pop () { whilestack.pop (); }
+ WhileElement & while_top () { return whilestack.top (); }
+ void while_push (const WhileElement & we) { whilestack.push (we); }
+
+ // Runner *********** TRON **************
+
+ void tron (bool fLine, BlChannel blc);
+ void troff ();
+ void tronline (const CodeLine & line)
+ { globalrunner.tronline (line); }
+
+ // Runner *********** BREAK / CONT **************
+private:
+ ProgramPos posbreak;
+public:
+ void jump_break ()
+ {
+ //if (! posbreak)
+ if (posbreak.getnum () == LineEndProgram ||
+ posbreak.getnum () == LineDirectCommand)
+ throw ErrNoContinue;
+ posgoto= posbreak;
+ //posbreak= 0;
+ posbreak= LineEndProgram;
+ status= Jump;
+ }
+ void set_break (ProgramPos pos) { posbreak= pos; }
+
+ #if 0
+ void setbreakstate (BreakState newstate)
+ {
+ breakstate= newstate;
+ }
+ BreakState getbreakstate () { return breakstate; }
+ void setbreakgosub (BlLineNumber bln)
+ {
+ breakstate= BreakGosub;
+ breakgosubline= bln;
+ }
+ BlLineNumber getbreakgosub () { return breakgosubline; }
+ #else
+
+ void setbreakstate (blassic::onbreak::BreakState newstate)
+ {
+ globalrunner.setbreakstate (newstate);
+ }
+ blassic::onbreak::BreakState getbreakstate () const
+ {
+ return globalrunner.getbreakstate ();
+ }
+ void setbreakgosub (BlLineNumber bln)
+ {
+ globalrunner.setbreakgosub (bln);
+ }
+ BlLineNumber getbreakgosub ()
+ {
+ return globalrunner.getbreakgosub ();
+ }
+
+ #endif
+
+
+ // Runner *********** DATA / READ / RESTORE **************
+
+ BlLineNumber & getdatanumline ()
+ { return globalrunner.getdatanumline (); }
+ BlChunk & getdatachunk ()
+ { return globalrunner.getdatachunk (); }
+ unsigned short & getdataelem ()
+ { return globalrunner.getdataelem (); }
+
+ // Runner *********** ON ERROR GOTO **************
+
+ void showfailerrorgoto () const;
+ void clearerrorgoto ()
+ { globalrunner.clearerrorgoto (); }
+ void seterrorgoto (BlLineNumber line, BlLineNumber source)
+ { globalrunner.seterrorgoto (line, source); }
+ BlLineNumber geterrorgoto () const
+ { return globalrunner.geterrorgoto (); }
+ BlLineNumber geterrorgotosource () const
+ { return globalrunner.geterrorgotosource (); }
+
+ // Runner *********** Channels **************
+
+ #if 0
+ void assign_channel_var
+ (const std::string & var, const std::string & value,
+ blassic::file::BlFile::Align align)
+ {
+ for (ChanFile::iterator it= chanfile.begin ();
+ it != chanfile.end ();
+ ++it)
+ {
+ it->second->assign (var, value, align);
+ }
+ }
+ #else
+ bool assign_channel_var
+ (const std::string & var, const Dimension & dim,
+ const std::string & value,
+ blassic::file::BlFile::Align align)
+ { return globalrunner.assign_channel_var (var, dim, value, align); }
+ #endif
+ bool assign_mid_channel_var
+ (const std::string & var, const Dimension & dim,
+ const std::string & value,
+ size_t inipos, std::string::size_type len)
+ {
+ return globalrunner.assign_mid_channel_var
+ (var, dim, value, inipos, len);
+ }
+ //bool isfileopen (BlChannel channel) const
+ //{ return chanfile.find (channel) != chanfile.end (); }
+ bool isfileopen (BlChannel channel) const
+ { return globalrunner.isfileopen (channel); }
+ BlChannel freefile () const
+ { return globalrunner.freefile (); }
+ blassic::file::BlFile & getfile (BlChannel channel) const
+ { return globalrunner.getfile (channel); }
+ blassic::file::BlFile & getfile0 () const
+ { return globalrunner.getfile (DefaultChannel); }
+ void setfile (BlChannel channel, blassic::file::BlFile * npfile)
+ { globalrunner.setfile (channel, npfile); }
+ void resetfile0 ()
+ { globalrunner.resetfile0 (); }
+ void close_all ()
+ { globalrunner.close_all (); }
+ void destroy_windows ()
+ { globalrunner.destroy_windows (); }
+ void closechannel (BlChannel channel)
+ { globalrunner.closechannel (channel); }
+ void windowswap (BlChannel ch1, BlChannel ch2)
+ { globalrunner.windowswap (ch1, ch2); }
+
+ void pollchannel (BlChannel ch, BlLineNumber line)
+ { globalrunner.pollchannel (ch, line); }
+ bool channelspolled ()
+ { return globalrunner.channelspolled (); }
+ BlLineNumber getpollnumber ()
+ { return globalrunner.getpollnumber (); }
+
+ void spectrumwindows ();
+
+ // Runner *********** DATA / READ / RESTORE **************
+
+ void setreadline (BlLineNumber bln)
+ { globalrunner.setreadline (bln); }
+ void clearreadline ()
+ { globalrunner.clearreadline (); }
+
+ // Runner *********** AUTO **************
+private:
+ BlLineNumber blnAuto, blnAutoInc;
+public:
+ void setauto (BlLineNumber line, BlLineNumber inc)
+ { blnAuto= line; blnAutoInc= inc; }
+
+ // Runner *********** Trigonometric mode **************
+ TrigonometricMode trigonometric_mode ()
+ { return globalrunner.trigonometric_mode (); }
+ void trigonometric_default ()
+ { globalrunner.trigonometric_default (); }
+ void trigonometric_mode (TrigonometricMode trigmode_n)
+ { globalrunner.trigonometric_mode (trigmode_n); }
+
+private:
+
+ bool processline (const std::string & line);
+
+public:
+ // Runner *********** Random number generator **************
+
+ BlNumber getrandom ()
+ { return globalrunner.getrandom (); }
+ void seedrandom (unsigned int value)
+ { globalrunner.seedrandom (value); }
+
+ // Runner *********** Auxiliars **************
+
+ void clean_input ();
+ void ring ();
+ void set_title (const std::string & str);
+};
+
+std::ostream & operator << (std::ostream & os, Runner::RunnerStatus status);
+
+#endif
+
+// Fin de runner.h
Un proyecto texto-plano.xyz