/*****
* stm.h
* Andy Hammerlindl 2002/8/30
*
* Statements are objects in the language that do something on their
* own. Statements are different from declarations in that statements
* do not modify the environment. Translation of a statements puts the
* stack code to run it into the instruction stream.
*****/
#ifndef STM_H
#define STM_H
#include "types.h"
#include "symbol.h"
#include "dec.h"
namespace trans {
class coenv;
}
namespace absyntax {
using trans::coenv;
using sym::symbol;
class stm : public runnable {
public:
stm(position pos)
: runnable(pos) {}
void prettyprint(ostream &out, Int indent);
void transAsField(coenv &e, record *) {
// Ignore the record.
trans(e);
}
void trans(coenv &e) = 0;
};
class emptyStm : public stm {
public:
emptyStm(position pos)
: stm(pos) {}
void prettyprint(ostream &out, Int indent);
void trans(coenv &) {}
};
// Wrapper around a block to use it as a statement.
class blockStm : public stm {
block *base;
public:
blockStm(position pos, block *base)
: stm(pos), base(base) {}
void prettyprint(ostream &out, Int indent) override;
void trans(coenv &e) override {
return base->trans(e);
}
// A block is guaranteed to return iff its last statement is
// guaranteed to return.
bool returns() override {
return base->returns();
}
void createSymMap(AsymptoteLsp::SymbolContext* symContext) override;
};
// A statement that consist of a single expression to evaluate.
class expStm : public stm {
exp *body;
public:
expStm(position pos, exp *body)
: stm(pos), body(body) {}
void prettyprint(ostream &out, Int indent) override;
void trans(coenv &e) override;
// Should be called when running an expStm at the interactive prompt.
// The code will "write" the value of the expression at the prompt if
// possible.
void interactiveTrans(coenv &e) override;
void createSymMap(AsymptoteLsp::SymbolContext* symContext) override;
};
class ifStm : public stm {
exp *test;
stm *onTrue;
stm *onFalse;
public:
ifStm(position pos, exp *test, stm* onTrue, stm* onFalse = 0)
: stm(pos), test(test), onTrue(onTrue), onFalse(onFalse) {}
void prettyprint(ostream &out, Int indent) override;
void trans(coenv &e) override;
// An if statement is guaranteed to return iff both its pieces are
// guaranteed to return.
bool returns() override {
if (onTrue == 0 || onFalse == 0)
return false;
return onTrue->returns() && onFalse->returns();
}
void createSymMap(AsymptoteLsp::SymbolContext* symContext) override;
};
class whileStm : public stm {
exp *test;
stm *body;
public:
whileStm(position pos, exp *test, stm *body)
: stm(pos), test(test), body(body) {}
void prettyprint(ostream &out, Int indent) override;
void trans(coenv &e) override;
void createSymMap(AsymptoteLsp::SymbolContext* symContext) override;
};
class doStm : public stm {
stm *body;
exp *test;
public:
doStm(position pos, stm *body, exp *test)
: stm(pos), body(body), test(test) {}
void prettyprint(ostream &out, Int indent) override;
void trans(coenv &e) override;
void createSymMap(AsymptoteLsp::SymbolContext* symContext) override;
};
class forStm : public stm {
runnable *init;
exp *test;
runnable *update;
stm *body;
public:
forStm(position pos, runnable *init, exp *test, runnable *update, stm *body)
: stm(pos), init(init), test(test), update(update), body(body) {}
void prettyprint(ostream &out, Int indent) override;
void trans(coenv &e) override;
void createSymMap(AsymptoteLsp::SymbolContext* symContext) override;
};
class extendedForStm : public stm {
astType *start;
symbol var;
exp *set;
stm *body;
public:
extendedForStm(position pos, astType *start, symbol var, exp *set, stm *body)
: stm(pos), start(start), var(var), set(set), body(body) {}
void createSymMap(AsymptoteLsp::SymbolContext* symContext) override;
void prettyprint(ostream &out, Int indent) override;
void trans(coenv &e) override;
};
class breakStm : public stm {
public:
breakStm(position pos)
: stm(pos) {}
void prettyprint(ostream &out, Int indent) override;
void trans(coenv &e) override;
};
class continueStm : public stm {
public:
continueStm(position pos)
: stm(pos) {}
void prettyprint(ostream &out, Int indent) override;
void trans(coenv &e) override;
};
class returnStm : public stm {
exp *value;
public:
returnStm(position pos, exp *value = 0)
: stm(pos), value(value) {}
void prettyprint(ostream &out, Int indent) override;
void trans(coenv &e) override;
// A return statement is, of course, guaranteed to return.
bool returns() override {
return true;
}
void createSymMap(AsymptoteLsp::SymbolContext* symContext) override;
};
// Used at the start of for loops.
class stmExpList : public stm {
mem::list<stm *> stms;
public:
stmExpList(position pos)
: stm(pos) {}
// To ensure list deallocates properly.
virtual ~stmExpList() {}
void add(stm *s) {
stms.push_back(s);
}
void prettyprint(ostream &out, Int indent);
void trans(coenv &e);
};
} // namespace absyntax
#endif