2019-01-19 18:28:07 +01:00
|
|
|
#include "stmtnode.hpp"
|
|
|
|
|
#include <map>
|
|
|
|
|
#include "codegen.hpp"
|
|
|
|
|
#include "declnode.hpp"
|
|
|
|
|
#include "environ.hpp"
|
|
|
|
|
#include "ex.hpp"
|
|
|
|
|
#include "exprnode.hpp"
|
|
|
|
|
#include "label.hpp"
|
|
|
|
|
#include "varnode.hpp"
|
2014-01-31 08:23:00 +13:00
|
|
|
|
2019-01-19 18:28:07 +01:00
|
|
|
static std::string fileLabel;
|
|
|
|
|
static std::map<std::string, std::string> fileMap;
|
2014-01-31 08:23:00 +13:00
|
|
|
|
2019-01-19 18:28:07 +01:00
|
|
|
StmtNode::StmtNode() : pos(-1) {}
|
2014-01-31 08:23:00 +13:00
|
|
|
|
2019-01-18 17:04:57 +01:00
|
|
|
void StmtNode::debug(int pos, Codegen* g)
|
|
|
|
|
{
|
2016-05-07 22:49:54 +02:00
|
|
|
if (g->debug) {
|
2019-01-18 17:04:57 +01:00
|
|
|
TNode* t = fileLabel.size() ? global(fileLabel) : iconst(0);
|
2016-05-07 22:49:54 +02:00
|
|
|
g->code(call("__bbDebugStmt", iconst(pos), t));
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-01-19 18:28:07 +01:00
|
|
|
void StmtNode::semant(Environ* e) {}
|
|
|
|
|
|
|
|
|
|
void StmtNode::translate(Codegen* g) {}
|
|
|
|
|
|
|
|
|
|
void StmtSeqNode::reset(const std::string& file, const std::string& lab)
|
2019-01-18 17:04:57 +01:00
|
|
|
{
|
2016-05-07 22:49:54 +02:00
|
|
|
fileLabel = "";
|
2014-01-31 08:23:00 +13:00
|
|
|
fileMap.clear();
|
|
|
|
|
|
2016-05-07 22:49:54 +02:00
|
|
|
fileMap[file] = lab;
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
|
|
|
|
|
2019-01-19 18:28:07 +01:00
|
|
|
StmtSeqNode::StmtSeqNode(const std::string& f) : file(f) {}
|
|
|
|
|
|
|
|
|
|
StmtSeqNode::~StmtSeqNode()
|
|
|
|
|
{
|
|
|
|
|
for (; stmts.size(); stmts.pop_back())
|
|
|
|
|
delete stmts.back();
|
|
|
|
|
}
|
|
|
|
|
|
2014-01-31 08:23:00 +13:00
|
|
|
////////////////////////
|
|
|
|
|
// Statement Sequence //
|
|
|
|
|
////////////////////////
|
2019-01-18 17:04:57 +01:00
|
|
|
void StmtSeqNode::semant(Environ* e)
|
|
|
|
|
{
|
2016-05-07 22:49:54 +02:00
|
|
|
for (int k = 0; k < stmts.size(); ++k) {
|
2019-01-18 17:04:57 +01:00
|
|
|
try {
|
|
|
|
|
stmts[k]->semant(e);
|
2019-01-19 18:28:07 +01:00
|
|
|
} catch (BlitzException& x) {
|
2019-01-18 17:04:57 +01:00
|
|
|
if (x.pos < 0)
|
|
|
|
|
x.pos = stmts[k]->pos;
|
|
|
|
|
if (!x.file.size())
|
|
|
|
|
x.file = file;
|
2016-05-07 22:49:54 +02:00
|
|
|
throw;
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-01-18 17:04:57 +01:00
|
|
|
void StmtSeqNode::translate(Codegen* g)
|
|
|
|
|
{
|
2019-01-19 18:28:07 +01:00
|
|
|
std::string t = fileLabel;
|
|
|
|
|
fileLabel = file.size() ? fileMap[file] : "";
|
2016-05-07 22:49:54 +02:00
|
|
|
for (int k = 0; k < stmts.size(); ++k) {
|
2019-01-18 17:04:57 +01:00
|
|
|
StmtNode* stmt = stmts[k];
|
2016-05-07 22:49:54 +02:00
|
|
|
stmt->debug(stmts[k]->pos, g);
|
|
|
|
|
try {
|
|
|
|
|
stmt->translate(g);
|
2019-01-19 18:28:07 +01:00
|
|
|
} catch (BlitzException& x) {
|
2019-01-18 17:04:57 +01:00
|
|
|
if (x.pos < 0)
|
|
|
|
|
x.pos = stmts[k]->pos;
|
|
|
|
|
if (!x.file.size())
|
|
|
|
|
x.file = file;
|
2016-05-07 22:49:54 +02:00
|
|
|
throw;
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
|
|
|
|
}
|
2016-05-07 22:49:54 +02:00
|
|
|
fileLabel = t;
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
|
|
|
|
|
2019-01-19 18:28:07 +01:00
|
|
|
void StmtSeqNode::push_back(StmtNode* s)
|
|
|
|
|
{
|
|
|
|
|
stmts.push_back(s);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int StmtSeqNode::size()
|
|
|
|
|
{
|
|
|
|
|
return stmts.size();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Include
|
|
|
|
|
IncludeNode::IncludeNode(const std::string& t, std::shared_ptr<StmtSeqNode> ss) : file(t), stmts(ss) {}
|
|
|
|
|
|
|
|
|
|
IncludeNode::~IncludeNode() {}
|
|
|
|
|
|
2019-01-18 17:04:57 +01:00
|
|
|
void IncludeNode::semant(Environ* e)
|
|
|
|
|
{
|
|
|
|
|
label = genLabel();
|
2016-05-07 22:49:54 +02:00
|
|
|
fileMap[file] = label;
|
2014-01-31 08:23:00 +13:00
|
|
|
|
2016-05-07 22:49:54 +02:00
|
|
|
stmts->semant(e);
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
|
|
|
|
|
2019-01-18 17:04:57 +01:00
|
|
|
void IncludeNode::translate(Codegen* g)
|
|
|
|
|
{
|
|
|
|
|
if (g->debug)
|
|
|
|
|
g->s_data(file, label);
|
2014-01-31 08:23:00 +13:00
|
|
|
|
2016-05-07 22:49:54 +02:00
|
|
|
stmts->translate(g);
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
|
|
|
|
|
2019-01-19 18:28:07 +01:00
|
|
|
// Declare Statement
|
|
|
|
|
DeclStmtNode::DeclStmtNode(DeclNode* d) : decl(d)
|
|
|
|
|
{
|
|
|
|
|
pos = d->pos;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DeclStmtNode::~DeclStmtNode()
|
|
|
|
|
{
|
|
|
|
|
delete decl;
|
|
|
|
|
}
|
|
|
|
|
|
2019-01-18 17:04:57 +01:00
|
|
|
void DeclStmtNode::semant(Environ* e)
|
|
|
|
|
{
|
2016-05-07 22:49:54 +02:00
|
|
|
decl->proto(e->decls, e);
|
|
|
|
|
decl->semant(e);
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
|
|
|
|
|
2019-01-18 17:04:57 +01:00
|
|
|
void DeclStmtNode::translate(Codegen* g)
|
|
|
|
|
{
|
2016-05-07 22:49:54 +02:00
|
|
|
decl->translate(g);
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
|
|
|
|
|
2019-01-19 18:28:07 +01:00
|
|
|
// Dim Array Statement
|
|
|
|
|
DimNode::DimNode(const std::string& i, const std::string& t, ExprSeqNode* e) : ident(i), tag(t), exprs(e) {}
|
|
|
|
|
|
|
|
|
|
DimNode::~DimNode()
|
|
|
|
|
{
|
|
|
|
|
delete exprs;
|
|
|
|
|
}
|
|
|
|
|
|
2019-01-18 17:04:57 +01:00
|
|
|
void DimNode::semant(Environ* e)
|
|
|
|
|
{
|
|
|
|
|
Type* t = tagType(tag, e);
|
|
|
|
|
if (Decl* d = e->findDecl(ident)) {
|
|
|
|
|
ArrayType* a = d->type->arrayType();
|
2019-01-19 18:28:07 +01:00
|
|
|
if (!a || a->size != exprs->size() || (t && a->type != t)) {
|
2016-05-07 22:49:54 +02:00
|
|
|
ex("Duplicate identifier");
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
2019-01-18 17:04:57 +01:00
|
|
|
sem_type = a;
|
|
|
|
|
sem_decl = 0;
|
2016-05-07 22:49:54 +02:00
|
|
|
} else {
|
2019-01-18 17:04:57 +01:00
|
|
|
if (e->level > 0)
|
|
|
|
|
ex("Array not found in main program");
|
|
|
|
|
if (!t)
|
|
|
|
|
t = Type::int_type;
|
2016-10-03 17:11:15 +02:00
|
|
|
sem_type = new ArrayType(t, exprs->size());
|
2016-05-07 22:49:54 +02:00
|
|
|
sem_decl = e->decls->insertDecl(ident, sem_type, DECL_ARRAY);
|
|
|
|
|
e->types.push_back(sem_type);
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
2016-05-07 22:49:54 +02:00
|
|
|
exprs->semant(e);
|
|
|
|
|
exprs->castTo(Type::int_type, e);
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
|
|
|
|
|
2019-01-18 17:04:57 +01:00
|
|
|
void DimNode::translate(Codegen* g)
|
|
|
|
|
{
|
|
|
|
|
TNode* t;
|
2016-05-07 22:49:54 +02:00
|
|
|
g->code(call("__bbUndimArray", global("_a" + ident)));
|
|
|
|
|
for (int k = 0; k < exprs->size(); ++k) {
|
|
|
|
|
t = add(global("_a" + ident), iconst(k * 4 + 12));
|
|
|
|
|
t = move(exprs->exprs[k]->translate(g), mem(t));
|
|
|
|
|
g->code(t);
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
2016-05-07 22:49:54 +02:00
|
|
|
g->code(call("__bbDimArray", global("_a" + ident)));
|
2014-01-31 08:23:00 +13:00
|
|
|
|
2019-01-18 17:04:57 +01:00
|
|
|
if (!sem_decl)
|
|
|
|
|
return;
|
2014-01-31 08:23:00 +13:00
|
|
|
|
2019-01-18 17:04:57 +01:00
|
|
|
int et, k;
|
2019-01-19 18:28:07 +01:00
|
|
|
Type* ty = sem_type->arrayType()->type;
|
2019-01-18 17:04:57 +01:00
|
|
|
if (ty == Type::int_type)
|
|
|
|
|
et = 1;
|
|
|
|
|
else if (ty == Type::float_type)
|
|
|
|
|
et = 2;
|
|
|
|
|
else if (ty == Type::string_type)
|
|
|
|
|
et = 3;
|
|
|
|
|
else
|
|
|
|
|
et = 5;
|
2014-01-31 08:23:00 +13:00
|
|
|
|
2016-05-07 22:49:54 +02:00
|
|
|
g->align_data(4);
|
|
|
|
|
g->i_data(0, "_a" + ident);
|
|
|
|
|
g->i_data(et);
|
|
|
|
|
g->i_data(exprs->size());
|
2019-01-18 17:04:57 +01:00
|
|
|
for (k = 0; k < exprs->size(); ++k)
|
|
|
|
|
g->i_data(0);
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
|
|
|
|
|
2019-01-19 18:28:07 +01:00
|
|
|
AssNode::AssNode(VarNode* var, ExprNode* expr) : var(var), expr(expr) {}
|
|
|
|
|
|
|
|
|
|
AssNode::~AssNode()
|
|
|
|
|
{
|
|
|
|
|
delete var;
|
|
|
|
|
delete expr;
|
|
|
|
|
}
|
|
|
|
|
|
2014-01-31 08:23:00 +13:00
|
|
|
////////////////
|
|
|
|
|
// Assignment //
|
|
|
|
|
////////////////
|
2019-01-18 17:04:57 +01:00
|
|
|
void AssNode::semant(Environ* e)
|
|
|
|
|
{
|
2016-05-07 22:49:54 +02:00
|
|
|
var->semant(e);
|
2019-01-18 17:04:57 +01:00
|
|
|
if (var->sem_type->constType())
|
|
|
|
|
ex("Constants can not be assigned to");
|
|
|
|
|
if (var->sem_type->vectorType())
|
|
|
|
|
ex("Blitz arrays can not be assigned to");
|
2016-05-07 22:49:54 +02:00
|
|
|
expr = expr->semant(e);
|
|
|
|
|
expr = expr->castTo(var->sem_type, e);
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
|
|
|
|
|
2019-01-18 17:04:57 +01:00
|
|
|
void AssNode::translate(Codegen* g)
|
|
|
|
|
{
|
2016-05-07 22:49:54 +02:00
|
|
|
g->code(var->store(g, expr->translate(g)));
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
|
|
|
|
|
2019-01-19 18:28:07 +01:00
|
|
|
ExprStmtNode::ExprStmtNode(ExprNode* e) : expr(e) {}
|
|
|
|
|
|
|
|
|
|
ExprStmtNode::~ExprStmtNode()
|
|
|
|
|
{
|
|
|
|
|
delete expr;
|
|
|
|
|
}
|
|
|
|
|
|
2014-01-31 08:23:00 +13:00
|
|
|
//////////////////////////
|
|
|
|
|
// Expression statement //
|
|
|
|
|
//////////////////////////
|
2019-01-18 17:04:57 +01:00
|
|
|
void ExprStmtNode::semant(Environ* e)
|
|
|
|
|
{
|
2016-05-07 22:49:54 +02:00
|
|
|
expr = expr->semant(e);
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
|
|
|
|
|
2019-01-18 17:04:57 +01:00
|
|
|
void ExprStmtNode::translate(Codegen* g)
|
|
|
|
|
{
|
|
|
|
|
TNode* t = expr->translate(g);
|
|
|
|
|
if (expr->sem_type == Type::string_type)
|
|
|
|
|
t = call("__bbStrRelease", t);
|
2016-05-07 22:49:54 +02:00
|
|
|
g->code(t);
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
|
|
|
|
|
2019-01-19 18:28:07 +01:00
|
|
|
LabelNode::LabelNode(const std::string& s, int sz) : ident(s), data_sz(sz) {}
|
|
|
|
|
|
2014-01-31 08:23:00 +13:00
|
|
|
////////////////
|
|
|
|
|
// user label //
|
|
|
|
|
////////////////
|
2019-01-18 17:04:57 +01:00
|
|
|
void LabelNode::semant(Environ* e)
|
|
|
|
|
{
|
|
|
|
|
if (Label* l = e->findLabel(ident)) {
|
|
|
|
|
if (l->def >= 0)
|
|
|
|
|
ex("duplicate label");
|
|
|
|
|
l->def = pos;
|
|
|
|
|
l->data_sz = data_sz;
|
|
|
|
|
} else
|
|
|
|
|
e->insertLabel(ident, pos, -1, data_sz);
|
2016-05-07 22:49:54 +02:00
|
|
|
ident = e->funcLabel + ident;
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
|
|
|
|
|
2019-01-18 17:04:57 +01:00
|
|
|
void LabelNode::translate(Codegen* g)
|
|
|
|
|
{
|
2016-05-07 22:49:54 +02:00
|
|
|
g->label("_l" + ident);
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
|
|
|
|
|
2019-01-19 18:28:07 +01:00
|
|
|
RestoreNode::RestoreNode(const std::string& i) : ident(i) {}
|
|
|
|
|
|
2014-01-31 08:23:00 +13:00
|
|
|
//////////////////
|
|
|
|
|
// Restore data //
|
|
|
|
|
//////////////////
|
2019-01-18 17:04:57 +01:00
|
|
|
void RestoreNode::semant(Environ* e)
|
|
|
|
|
{
|
|
|
|
|
if (e->level > 0)
|
|
|
|
|
e = e->globals;
|
2014-01-31 08:23:00 +13:00
|
|
|
|
2019-01-18 17:04:57 +01:00
|
|
|
if (ident.size() == 0)
|
|
|
|
|
sem_label = 0;
|
2016-05-07 22:49:54 +02:00
|
|
|
else {
|
|
|
|
|
sem_label = e->findLabel(ident);
|
2019-01-18 17:04:57 +01:00
|
|
|
if (!sem_label)
|
|
|
|
|
sem_label = e->insertLabel(ident, -1, pos, -1);
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-01-18 17:04:57 +01:00
|
|
|
void RestoreNode::translate(Codegen* g)
|
|
|
|
|
{
|
|
|
|
|
TNode* t = global("__DATA");
|
|
|
|
|
if (sem_label)
|
|
|
|
|
t = add(t, iconst(sem_label->data_sz * 8));
|
2016-05-07 22:49:54 +02:00
|
|
|
g->code(call("__bbRestore", t));
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
|
|
|
|
|
2019-01-19 18:28:07 +01:00
|
|
|
GotoNode::GotoNode(const std::string& s) : ident(s) {}
|
|
|
|
|
|
2014-01-31 08:23:00 +13:00
|
|
|
////////////////////
|
|
|
|
|
// Goto statement //
|
|
|
|
|
////////////////////
|
2019-01-18 17:04:57 +01:00
|
|
|
void GotoNode::semant(Environ* e)
|
|
|
|
|
{
|
2016-05-07 22:49:54 +02:00
|
|
|
if (!e->findLabel(ident)) {
|
|
|
|
|
e->insertLabel(ident, -1, pos, -1);
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
2016-05-07 22:49:54 +02:00
|
|
|
ident = e->funcLabel + ident;
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
|
|
|
|
|
2019-01-18 17:04:57 +01:00
|
|
|
void GotoNode::translate(Codegen* g)
|
|
|
|
|
{
|
2016-05-07 22:49:54 +02:00
|
|
|
g->code(jump("_l" + ident));
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
|
|
|
|
|
2019-01-19 18:28:07 +01:00
|
|
|
GosubNode::GosubNode(const std::string& s) : ident(s) {}
|
|
|
|
|
|
2014-01-31 08:23:00 +13:00
|
|
|
/////////////////////
|
|
|
|
|
// Gosub statement //
|
|
|
|
|
/////////////////////
|
2019-01-18 17:04:57 +01:00
|
|
|
void GosubNode::semant(Environ* e)
|
|
|
|
|
{
|
|
|
|
|
if (e->level > 0)
|
|
|
|
|
ex("'Gosub' may not be used inside a function");
|
|
|
|
|
if (!e->findLabel(ident))
|
|
|
|
|
e->insertLabel(ident, -1, pos, -1);
|
2016-05-07 22:49:54 +02:00
|
|
|
ident = e->funcLabel + ident;
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
|
|
|
|
|
2019-01-18 17:04:57 +01:00
|
|
|
void GosubNode::translate(Codegen* g)
|
|
|
|
|
{
|
2016-05-07 22:49:54 +02:00
|
|
|
g->code(jsr("_l" + ident));
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
|
|
|
|
|
2019-01-19 18:28:07 +01:00
|
|
|
IfNode::IfNode(ExprNode* e, StmtSeqNode* s, StmtSeqNode* o) : expr(e), stmts(s), elseOpt(o) {}
|
|
|
|
|
|
|
|
|
|
IfNode::~IfNode()
|
|
|
|
|
{
|
|
|
|
|
delete expr;
|
|
|
|
|
delete stmts;
|
|
|
|
|
delete elseOpt;
|
|
|
|
|
}
|
|
|
|
|
|
2014-01-31 08:23:00 +13:00
|
|
|
//////////////////
|
|
|
|
|
// If statement //
|
|
|
|
|
//////////////////
|
2019-01-18 17:04:57 +01:00
|
|
|
void IfNode::semant(Environ* e)
|
|
|
|
|
{
|
2016-05-07 22:49:54 +02:00
|
|
|
expr = expr->semant(e);
|
|
|
|
|
expr = expr->castTo(Type::int_type, e);
|
|
|
|
|
stmts->semant(e);
|
2019-01-18 17:04:57 +01:00
|
|
|
if (elseOpt)
|
|
|
|
|
elseOpt->semant(e);
|
2016-05-07 22:49:54 +02:00
|
|
|
}
|
|
|
|
|
|
2019-01-18 17:04:57 +01:00
|
|
|
void IfNode::translate(Codegen* g)
|
|
|
|
|
{
|
|
|
|
|
if (ConstNode* c = expr->constNode()) {
|
|
|
|
|
if (c->intValue())
|
|
|
|
|
stmts->translate(g);
|
|
|
|
|
else if (elseOpt)
|
|
|
|
|
elseOpt->translate(g);
|
2016-05-07 22:49:54 +02:00
|
|
|
} else {
|
2019-01-19 18:28:07 +01:00
|
|
|
std::string _else = genLabel();
|
2016-05-07 22:49:54 +02:00
|
|
|
g->code(jumpf(expr->translate(g), _else));
|
|
|
|
|
stmts->translate(g);
|
|
|
|
|
if (elseOpt) {
|
2019-01-19 18:28:07 +01:00
|
|
|
std::string _else2 = genLabel();
|
2016-05-07 22:49:54 +02:00
|
|
|
g->code(jump(_else2));
|
|
|
|
|
g->label(_else);
|
|
|
|
|
elseOpt->translate(g);
|
|
|
|
|
_else = _else2;
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
2016-05-07 22:49:54 +02:00
|
|
|
g->label(_else);
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
///////////
|
|
|
|
|
// Break //
|
|
|
|
|
///////////
|
2019-01-18 17:04:57 +01:00
|
|
|
void ExitNode::semant(Environ* e)
|
|
|
|
|
{
|
2016-05-07 22:49:54 +02:00
|
|
|
sem_brk = e->breakLabel;
|
2019-01-18 17:04:57 +01:00
|
|
|
if (!sem_brk.size())
|
|
|
|
|
ex("break must appear inside a loop");
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
|
|
|
|
|
2019-01-18 17:04:57 +01:00
|
|
|
void ExitNode::translate(Codegen* g)
|
|
|
|
|
{
|
2016-10-03 17:11:15 +02:00
|
|
|
g->code(new TNode(IR_JUMP, 0, 0, sem_brk));
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
|
|
|
|
|
2019-01-19 18:28:07 +01:00
|
|
|
WhileNode::WhileNode(ExprNode* e, StmtSeqNode* s, int wp) : expr(e), stmts(s), wendPos(wp) {}
|
|
|
|
|
|
|
|
|
|
WhileNode::~WhileNode()
|
|
|
|
|
{
|
|
|
|
|
delete expr;
|
|
|
|
|
delete stmts;
|
|
|
|
|
}
|
|
|
|
|
|
2014-01-31 08:23:00 +13:00
|
|
|
/////////////////////
|
|
|
|
|
// While statement //
|
|
|
|
|
/////////////////////
|
2019-01-18 17:04:57 +01:00
|
|
|
void WhileNode::semant(Environ* e)
|
|
|
|
|
{
|
2019-01-19 18:28:07 +01:00
|
|
|
expr = expr->semant(e);
|
|
|
|
|
expr = expr->castTo(Type::int_type, e);
|
|
|
|
|
std::string brk = e->setBreak(sem_brk = genLabel());
|
2016-05-07 22:49:54 +02:00
|
|
|
stmts->semant(e);
|
|
|
|
|
e->setBreak(brk);
|
|
|
|
|
}
|
|
|
|
|
|
2019-01-18 17:04:57 +01:00
|
|
|
void WhileNode::translate(Codegen* g)
|
|
|
|
|
{
|
2019-01-19 18:28:07 +01:00
|
|
|
std::string loop = genLabel();
|
2019-01-18 17:04:57 +01:00
|
|
|
if (ConstNode* c = expr->constNode()) {
|
|
|
|
|
if (!c->intValue())
|
|
|
|
|
return;
|
2016-05-07 22:49:54 +02:00
|
|
|
g->label(loop);
|
|
|
|
|
stmts->translate(g);
|
|
|
|
|
g->code(jump(loop));
|
|
|
|
|
} else {
|
2019-01-19 18:28:07 +01:00
|
|
|
std::string cond = genLabel();
|
2016-05-07 22:49:54 +02:00
|
|
|
g->code(jump(cond));
|
|
|
|
|
g->label(loop);
|
|
|
|
|
stmts->translate(g);
|
|
|
|
|
debug(wendPos, g);
|
|
|
|
|
g->label(cond);
|
|
|
|
|
g->code(jumpt(expr->translate(g), loop));
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
2016-05-07 22:49:54 +02:00
|
|
|
g->label(sem_brk);
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
///////////////////
|
|
|
|
|
// For/Next loop //
|
|
|
|
|
///////////////////
|
2019-01-18 17:04:57 +01:00
|
|
|
ForNode::ForNode(VarNode* var, ExprNode* from, ExprNode* to, ExprNode* step, StmtSeqNode* ss, int np)
|
|
|
|
|
: var(var), fromExpr(from), toExpr(to), stepExpr(step), stmts(ss), nextPos(np)
|
|
|
|
|
{}
|
2014-01-31 08:23:00 +13:00
|
|
|
|
2019-01-18 17:04:57 +01:00
|
|
|
ForNode::~ForNode()
|
|
|
|
|
{
|
2014-01-31 08:23:00 +13:00
|
|
|
delete stmts;
|
|
|
|
|
delete stepExpr;
|
|
|
|
|
delete toExpr;
|
|
|
|
|
delete fromExpr;
|
|
|
|
|
delete var;
|
|
|
|
|
}
|
|
|
|
|
|
2019-01-18 17:04:57 +01:00
|
|
|
void ForNode::semant(Environ* e)
|
|
|
|
|
{
|
2016-05-07 22:49:54 +02:00
|
|
|
var->semant(e);
|
2019-01-18 17:04:57 +01:00
|
|
|
Type* ty = var->sem_type;
|
|
|
|
|
if (ty->constType())
|
|
|
|
|
ex("Index variable can not be constant");
|
2016-05-07 22:49:54 +02:00
|
|
|
if (ty != Type::int_type && ty != Type::float_type) {
|
|
|
|
|
ex("index variable must be integer or real");
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
2016-05-07 22:49:54 +02:00
|
|
|
fromExpr = fromExpr->semant(e);
|
|
|
|
|
fromExpr = fromExpr->castTo(ty, e);
|
2019-01-18 17:04:57 +01:00
|
|
|
toExpr = toExpr->semant(e);
|
|
|
|
|
toExpr = toExpr->castTo(ty, e);
|
2016-05-07 22:49:54 +02:00
|
|
|
stepExpr = stepExpr->semant(e);
|
|
|
|
|
stepExpr = stepExpr->castTo(ty, e);
|
2014-01-31 08:23:00 +13:00
|
|
|
|
2019-01-18 17:04:57 +01:00
|
|
|
if (!stepExpr->constNode())
|
|
|
|
|
ex("Step value must be constant");
|
2014-01-31 08:23:00 +13:00
|
|
|
|
2019-01-19 18:28:07 +01:00
|
|
|
std::string brk = e->setBreak(sem_brk = genLabel());
|
2016-05-07 22:49:54 +02:00
|
|
|
stmts->semant(e);
|
|
|
|
|
e->setBreak(brk);
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
|
|
|
|
|
2019-01-18 17:04:57 +01:00
|
|
|
void ForNode::translate(Codegen* g)
|
|
|
|
|
{
|
|
|
|
|
TNode* t;
|
|
|
|
|
Type* ty = var->sem_type;
|
2014-01-31 08:23:00 +13:00
|
|
|
|
|
|
|
|
//initial assignment
|
2016-05-07 22:49:54 +02:00
|
|
|
g->code(var->store(g, fromExpr->translate(g)));
|
2014-01-31 08:23:00 +13:00
|
|
|
|
2019-01-19 18:28:07 +01:00
|
|
|
std::string cond = genLabel();
|
|
|
|
|
std::string loop = genLabel();
|
2016-05-07 22:49:54 +02:00
|
|
|
g->code(jump(cond));
|
|
|
|
|
g->label(loop);
|
|
|
|
|
stmts->translate(g);
|
2014-01-31 08:23:00 +13:00
|
|
|
|
|
|
|
|
//execute the step part
|
2016-05-07 22:49:54 +02:00
|
|
|
debug(nextPos, g);
|
|
|
|
|
int op = ty == Type::int_type ? IR_ADD : IR_FADD;
|
2019-01-18 17:04:57 +01:00
|
|
|
t = new TNode(op, var->load(g), stepExpr->translate(g));
|
2016-05-07 22:49:54 +02:00
|
|
|
g->code(var->store(g, t));
|
2014-01-31 08:23:00 +13:00
|
|
|
|
|
|
|
|
//test for loop cond
|
2016-05-07 22:49:54 +02:00
|
|
|
g->label(cond);
|
|
|
|
|
op = stepExpr->constNode()->floatValue() > 0 ? '>' : '<';
|
2019-01-18 17:04:57 +01:00
|
|
|
t = compare(op, var->load(g), toExpr->translate(g), ty);
|
2016-05-07 22:49:54 +02:00
|
|
|
g->code(jumpf(t, loop));
|
2014-01-31 08:23:00 +13:00
|
|
|
|
2016-05-07 22:49:54 +02:00
|
|
|
g->label(sem_brk);
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
|
|
|
|
|
2019-01-19 18:28:07 +01:00
|
|
|
ForEachNode::ForEachNode(VarNode* v, const std::string& t, StmtSeqNode* s, int np)
|
|
|
|
|
: var(v), typeIdent(t), stmts(s), nextPos(np)
|
|
|
|
|
{}
|
|
|
|
|
|
|
|
|
|
ForEachNode::~ForEachNode()
|
|
|
|
|
{
|
|
|
|
|
delete var;
|
|
|
|
|
delete stmts;
|
|
|
|
|
}
|
|
|
|
|
|
2014-01-31 08:23:00 +13:00
|
|
|
///////////////////////////////
|
|
|
|
|
// For each object of a type //
|
|
|
|
|
///////////////////////////////
|
2019-01-18 17:04:57 +01:00
|
|
|
void ForEachNode::semant(Environ* e)
|
|
|
|
|
{
|
2016-05-07 22:49:54 +02:00
|
|
|
var->semant(e);
|
2019-01-18 17:04:57 +01:00
|
|
|
Type* ty = var->sem_type;
|
2014-01-31 08:23:00 +13:00
|
|
|
|
2019-01-18 17:04:57 +01:00
|
|
|
if (ty->structType() == 0)
|
|
|
|
|
ex("Index variable is not a NewType");
|
|
|
|
|
Type* t = e->findType(typeIdent);
|
|
|
|
|
if (!t)
|
|
|
|
|
ex("Type name not found");
|
|
|
|
|
if (t != ty)
|
|
|
|
|
ex("Type mismatch");
|
2014-01-31 08:23:00 +13:00
|
|
|
|
2019-01-19 18:28:07 +01:00
|
|
|
std::string brk = e->setBreak(sem_brk = genLabel());
|
2016-05-07 22:49:54 +02:00
|
|
|
stmts->semant(e);
|
|
|
|
|
e->setBreak(brk);
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
|
|
|
|
|
2019-01-18 17:04:57 +01:00
|
|
|
void ForEachNode::translate(Codegen* g)
|
|
|
|
|
{
|
2019-01-19 18:28:07 +01:00
|
|
|
TNode * t, *l, *r;
|
|
|
|
|
std::string _loop = genLabel();
|
2014-01-31 08:23:00 +13:00
|
|
|
|
2019-01-19 18:28:07 +01:00
|
|
|
std::string objFirst, objNext;
|
2014-01-31 08:23:00 +13:00
|
|
|
|
2016-05-07 22:49:54 +02:00
|
|
|
if (var->isObjParam()) {
|
|
|
|
|
objFirst = "__bbObjEachFirst2";
|
2019-01-18 17:04:57 +01:00
|
|
|
objNext = "__bbObjEachNext2";
|
2016-05-07 22:49:54 +02:00
|
|
|
} else {
|
|
|
|
|
objFirst = "__bbObjEachFirst";
|
2019-01-18 17:04:57 +01:00
|
|
|
objNext = "__bbObjEachNext";
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
|
|
|
|
|
2016-05-07 22:49:54 +02:00
|
|
|
l = var->translate(g);
|
|
|
|
|
r = global("_t" + typeIdent);
|
|
|
|
|
t = jumpf(call(objFirst, l, r), sem_brk);
|
|
|
|
|
g->code(t);
|
2014-01-31 08:23:00 +13:00
|
|
|
|
2016-05-07 22:49:54 +02:00
|
|
|
g->label(_loop);
|
|
|
|
|
stmts->translate(g);
|
2014-01-31 08:23:00 +13:00
|
|
|
|
2016-05-07 22:49:54 +02:00
|
|
|
debug(nextPos, g);
|
|
|
|
|
t = jumpt(call(objNext, var->translate(g)), _loop);
|
|
|
|
|
g->code(t);
|
2014-01-31 08:23:00 +13:00
|
|
|
|
2016-05-07 22:49:54 +02:00
|
|
|
g->label(sem_brk);
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
|
|
|
|
|
2019-01-19 18:28:07 +01:00
|
|
|
ReturnNode::ReturnNode(ExprNode* e) : expr(e) {}
|
|
|
|
|
|
|
|
|
|
ReturnNode::~ReturnNode()
|
|
|
|
|
{
|
|
|
|
|
delete expr;
|
|
|
|
|
}
|
|
|
|
|
|
2014-01-31 08:23:00 +13:00
|
|
|
////////////////////////////
|
|
|
|
|
// Return from a function //
|
|
|
|
|
////////////////////////////
|
2019-01-18 17:04:57 +01:00
|
|
|
void ReturnNode::semant(Environ* e)
|
|
|
|
|
{
|
2016-05-07 22:49:54 +02:00
|
|
|
if (e->level <= 0 && expr) {
|
|
|
|
|
ex("Main program cannot return a value");
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
2016-05-07 22:49:54 +02:00
|
|
|
if (e->level > 0) {
|
|
|
|
|
if (!expr) {
|
|
|
|
|
if (e->returnType == Type::float_type) {
|
2016-10-03 17:11:15 +02:00
|
|
|
expr = new FloatConstNode(0);
|
2016-05-07 22:49:54 +02:00
|
|
|
} else if (e->returnType == Type::string_type) {
|
2016-10-03 17:11:15 +02:00
|
|
|
expr = new StringConstNode("");
|
2016-05-07 22:49:54 +02:00
|
|
|
} else if (e->returnType->structType()) {
|
2016-10-03 17:11:15 +02:00
|
|
|
expr = new NullNode();
|
2016-05-07 22:49:54 +02:00
|
|
|
} else {
|
2016-10-03 17:11:15 +02:00
|
|
|
expr = new IntConstNode(0);
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
|
|
|
|
}
|
2019-01-18 17:04:57 +01:00
|
|
|
expr = expr->semant(e);
|
|
|
|
|
expr = expr->castTo(e->returnType, e);
|
2016-05-07 22:49:54 +02:00
|
|
|
returnLabel = e->funcLabel + "_leave";
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-01-18 17:04:57 +01:00
|
|
|
void ReturnNode::translate(Codegen* g)
|
|
|
|
|
{
|
2016-05-07 22:49:54 +02:00
|
|
|
if (!expr) {
|
2016-10-03 17:11:15 +02:00
|
|
|
g->code(new TNode(IR_RET, 0, 0));
|
2014-01-31 08:23:00 +13:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2019-01-18 17:04:57 +01:00
|
|
|
TNode* t = expr->translate(g);
|
2014-01-31 08:23:00 +13:00
|
|
|
|
2016-05-07 22:49:54 +02:00
|
|
|
if (expr->sem_type == Type::float_type) {
|
2016-10-03 17:11:15 +02:00
|
|
|
g->code(new TNode(IR_FRETURN, t, 0, returnLabel));
|
2016-05-07 22:49:54 +02:00
|
|
|
} else {
|
2016-10-03 17:11:15 +02:00
|
|
|
g->code(new TNode(IR_RETURN, t, 0, returnLabel));
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-01-19 18:28:07 +01:00
|
|
|
DeleteNode::DeleteNode(ExprNode* e) : expr(e) {}
|
|
|
|
|
|
|
|
|
|
DeleteNode::~DeleteNode()
|
|
|
|
|
{
|
|
|
|
|
delete expr;
|
|
|
|
|
}
|
|
|
|
|
|
2014-01-31 08:23:00 +13:00
|
|
|
//////////////////////
|
|
|
|
|
// Delete statement //
|
|
|
|
|
//////////////////////
|
2019-01-18 17:04:57 +01:00
|
|
|
void DeleteNode::semant(Environ* e)
|
|
|
|
|
{
|
2016-05-07 22:49:54 +02:00
|
|
|
expr = expr->semant(e);
|
2019-01-18 17:04:57 +01:00
|
|
|
if (expr->sem_type->structType() == 0)
|
|
|
|
|
ex("Can't delete non-Newtype");
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
|
|
|
|
|
2019-01-18 17:04:57 +01:00
|
|
|
void DeleteNode::translate(Codegen* g)
|
|
|
|
|
{
|
|
|
|
|
TNode* t = expr->translate(g);
|
2016-05-07 22:49:54 +02:00
|
|
|
g->code(call("__bbObjDelete", t));
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
|
|
|
|
|
2019-01-19 18:28:07 +01:00
|
|
|
DeleteEachNode::DeleteEachNode(const std::string& t) : typeIdent(t) {}
|
|
|
|
|
|
2014-01-31 08:23:00 +13:00
|
|
|
///////////////////////////
|
|
|
|
|
// Delete each of a type //
|
|
|
|
|
///////////////////////////
|
2019-01-18 17:04:57 +01:00
|
|
|
void DeleteEachNode::semant(Environ* e)
|
|
|
|
|
{
|
|
|
|
|
Type* t = e->findType(typeIdent);
|
|
|
|
|
if (!t || t->structType() == 0)
|
|
|
|
|
ex("Specified name is not a NewType name");
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
|
|
|
|
|
2019-01-18 17:04:57 +01:00
|
|
|
void DeleteEachNode::translate(Codegen* g)
|
|
|
|
|
{
|
2016-05-07 22:49:54 +02:00
|
|
|
g->code(call("__bbObjDeleteEach", global("_t" + typeIdent)));
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
|
|
|
|
|
2019-01-19 18:28:07 +01:00
|
|
|
InsertNode::InsertNode(ExprNode* e1, ExprNode* e2, bool b) : expr1(e1), expr2(e2), before(b) {}
|
|
|
|
|
|
|
|
|
|
InsertNode::~InsertNode()
|
|
|
|
|
{
|
|
|
|
|
delete expr1;
|
|
|
|
|
delete expr2;
|
|
|
|
|
}
|
|
|
|
|
|
2014-01-31 08:23:00 +13:00
|
|
|
///////////////////////////
|
|
|
|
|
// Insert object in list //
|
|
|
|
|
///////////////////////////
|
2019-01-18 17:04:57 +01:00
|
|
|
void InsertNode::semant(Environ* e)
|
|
|
|
|
{
|
|
|
|
|
expr1 = expr1->semant(e);
|
|
|
|
|
expr2 = expr2->semant(e);
|
|
|
|
|
StructType* t1 = expr1->sem_type->structType();
|
|
|
|
|
StructType* t2 = expr2->sem_type->structType();
|
|
|
|
|
if (!t1 || !t2)
|
|
|
|
|
ex("Illegal expression type");
|
|
|
|
|
if (t1 != t2)
|
|
|
|
|
ex("Objects types are differnt");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void InsertNode::translate(Codegen* g)
|
|
|
|
|
{
|
|
|
|
|
TNode* t1 = expr1->translate(g);
|
|
|
|
|
if (g->debug)
|
|
|
|
|
t1 = jumpf(t1, "__bbNullObjEx");
|
|
|
|
|
TNode* t2 = expr2->translate(g);
|
|
|
|
|
if (g->debug)
|
|
|
|
|
t2 = jumpf(t2, "__bbNullObjEx");
|
2019-01-19 18:28:07 +01:00
|
|
|
std::string s = before ? "__bbObjInsBefore" : "__bbObjInsAfter";
|
2016-05-07 22:49:54 +02:00
|
|
|
g->code(call(s, t1, t2));
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
|
|
|
|
|
2019-01-19 18:28:07 +01:00
|
|
|
SelectNode::SelectNode(ExprNode* e) : expr(e), defStmts(0), sem_temp(0) {}
|
|
|
|
|
|
|
|
|
|
SelectNode::~SelectNode()
|
|
|
|
|
{
|
|
|
|
|
delete expr;
|
|
|
|
|
delete defStmts;
|
|
|
|
|
delete sem_temp;
|
|
|
|
|
for (; cases.size(); cases.pop_back())
|
|
|
|
|
delete cases.back();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SelectNode::push_back(CaseNode* c)
|
|
|
|
|
{
|
|
|
|
|
cases.push_back(c);
|
|
|
|
|
}
|
|
|
|
|
|
2014-01-31 08:23:00 +13:00
|
|
|
////////////////////////
|
|
|
|
|
// A select statement //
|
|
|
|
|
////////////////////////
|
2019-01-18 17:04:57 +01:00
|
|
|
void SelectNode::semant(Environ* e)
|
|
|
|
|
{
|
|
|
|
|
expr = expr->semant(e);
|
|
|
|
|
Type* ty = expr->sem_type;
|
|
|
|
|
if (ty->structType())
|
|
|
|
|
ex("Select cannot be used with objects");
|
2014-01-31 08:23:00 +13:00
|
|
|
|
|
|
|
|
//we need a temp var
|
2019-01-18 17:04:57 +01:00
|
|
|
Decl* d = e->decls->insertDecl(genLabel(), expr->sem_type, DECL_LOCAL);
|
2016-10-03 17:11:15 +02:00
|
|
|
sem_temp = new DeclVarNode(d);
|
2016-05-07 22:49:54 +02:00
|
|
|
|
|
|
|
|
for (int k = 0; k < cases.size(); ++k) {
|
2019-01-18 17:04:57 +01:00
|
|
|
CaseNode* c = cases[k];
|
2016-05-07 22:49:54 +02:00
|
|
|
c->exprs->semant(e);
|
|
|
|
|
c->exprs->castTo(ty, e);
|
|
|
|
|
c->stmts->semant(e);
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
2019-01-18 17:04:57 +01:00
|
|
|
if (defStmts)
|
|
|
|
|
defStmts->semant(e);
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
|
|
|
|
|
2019-01-18 17:04:57 +01:00
|
|
|
void SelectNode::translate(Codegen* g)
|
|
|
|
|
{
|
|
|
|
|
Type* ty = expr->sem_type;
|
|
|
|
|
int k;
|
2014-01-31 08:23:00 +13:00
|
|
|
|
2016-05-07 22:49:54 +02:00
|
|
|
g->code(sem_temp->store(g, expr->translate(g)));
|
2014-01-31 08:23:00 +13:00
|
|
|
|
2019-01-19 18:28:07 +01:00
|
|
|
std::vector<std::string> labs;
|
|
|
|
|
std::string brk = genLabel();
|
2016-05-07 22:49:54 +02:00
|
|
|
|
|
|
|
|
for (k = 0; k < cases.size(); ++k) {
|
2019-01-18 17:04:57 +01:00
|
|
|
CaseNode* c = cases[k];
|
2016-05-07 22:49:54 +02:00
|
|
|
labs.push_back(genLabel());
|
|
|
|
|
for (int j = 0; j < c->exprs->size(); ++j) {
|
2019-01-18 17:04:57 +01:00
|
|
|
ExprNode* e = c->exprs->exprs[j];
|
|
|
|
|
TNode* t = compare('=', sem_temp->load(g), e->translate(g), ty);
|
2016-05-07 22:49:54 +02:00
|
|
|
g->code(jumpt(t, labs.back()));
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
|
|
|
|
}
|
2019-01-18 17:04:57 +01:00
|
|
|
if (defStmts)
|
|
|
|
|
defStmts->translate(g);
|
2016-05-07 22:49:54 +02:00
|
|
|
g->code(jump(brk));
|
|
|
|
|
for (k = 0; k < cases.size(); ++k) {
|
2019-01-18 17:04:57 +01:00
|
|
|
CaseNode* c = cases[k];
|
2016-05-07 22:49:54 +02:00
|
|
|
g->label(labs[k]);
|
|
|
|
|
c->stmts->translate(g);
|
|
|
|
|
g->code(jump(brk));
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
|
|
|
|
|
2016-05-07 22:49:54 +02:00
|
|
|
g->label(brk);
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
|
|
|
|
|
2019-01-19 18:28:07 +01:00
|
|
|
RepeatNode::RepeatNode(StmtSeqNode* s, ExprNode* e, int up) : stmts(s), expr(e), untilPos(up) {}
|
|
|
|
|
|
|
|
|
|
RepeatNode::~RepeatNode()
|
|
|
|
|
{
|
|
|
|
|
delete stmts;
|
|
|
|
|
delete expr;
|
|
|
|
|
}
|
|
|
|
|
|
2014-01-31 08:23:00 +13:00
|
|
|
////////////////////////////
|
|
|
|
|
// Repeat...Until/Forever //
|
|
|
|
|
////////////////////////////
|
2019-01-18 17:04:57 +01:00
|
|
|
void RepeatNode::semant(Environ* e)
|
|
|
|
|
{
|
2019-01-19 18:28:07 +01:00
|
|
|
sem_brk = genLabel();
|
|
|
|
|
std::string brk = e->setBreak(sem_brk);
|
2016-05-07 22:49:54 +02:00
|
|
|
stmts->semant(e);
|
|
|
|
|
e->setBreak(brk);
|
|
|
|
|
if (expr) {
|
|
|
|
|
expr = expr->semant(e);
|
|
|
|
|
expr = expr->castTo(Type::int_type, e);
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-01-18 17:04:57 +01:00
|
|
|
void RepeatNode::translate(Codegen* g)
|
|
|
|
|
{
|
2019-01-19 18:28:07 +01:00
|
|
|
std::string loop = genLabel();
|
2016-05-07 22:49:54 +02:00
|
|
|
g->label(loop);
|
|
|
|
|
stmts->translate(g);
|
|
|
|
|
debug(untilPos, g);
|
2014-01-31 08:23:00 +13:00
|
|
|
|
2019-01-18 17:04:57 +01:00
|
|
|
if (ConstNode* c = expr ? expr->constNode() : 0) {
|
|
|
|
|
if (!c->intValue())
|
|
|
|
|
g->code(jump(loop));
|
2016-05-07 22:49:54 +02:00
|
|
|
} else {
|
2019-01-18 17:04:57 +01:00
|
|
|
if (expr)
|
|
|
|
|
g->code(jumpf(expr->translate(g), loop));
|
|
|
|
|
else
|
|
|
|
|
g->code(jump(loop));
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
2016-05-07 22:49:54 +02:00
|
|
|
g->label(sem_brk);
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
|
|
|
|
|
2019-01-19 18:28:07 +01:00
|
|
|
ReadNode::ReadNode(VarNode* v) : var(v) {}
|
|
|
|
|
|
|
|
|
|
ReadNode::~ReadNode()
|
|
|
|
|
{
|
|
|
|
|
delete var;
|
|
|
|
|
}
|
|
|
|
|
|
2014-01-31 08:23:00 +13:00
|
|
|
///////////////
|
|
|
|
|
// Read data //
|
|
|
|
|
///////////////
|
2019-01-18 17:04:57 +01:00
|
|
|
void ReadNode::semant(Environ* e)
|
|
|
|
|
{
|
2016-05-07 22:49:54 +02:00
|
|
|
var->semant(e);
|
2019-01-18 17:04:57 +01:00
|
|
|
if (var->sem_type->constType())
|
|
|
|
|
ex("Constants can not be modified");
|
|
|
|
|
if (var->sem_type->structType())
|
|
|
|
|
ex("Data can not be read into an object");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ReadNode::translate(Codegen* g)
|
|
|
|
|
{
|
|
|
|
|
TNode* t;
|
|
|
|
|
if (var->sem_type == Type::int_type)
|
|
|
|
|
t = call("__bbReadInt");
|
|
|
|
|
else if (var->sem_type == Type::float_type)
|
|
|
|
|
t = fcall("__bbReadFloat");
|
|
|
|
|
else
|
|
|
|
|
t = call("__bbReadStr");
|
2016-05-07 22:49:54 +02:00
|
|
|
g->code(var->store(g, t));
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
2019-01-19 18:28:07 +01:00
|
|
|
|
|
|
|
|
CaseNode::CaseNode(ExprSeqNode* e, StmtSeqNode* s) : exprs(e), stmts(s) {}
|
|
|
|
|
|
|
|
|
|
CaseNode::~CaseNode()
|
|
|
|
|
{
|
|
|
|
|
delete exprs;
|
|
|
|
|
delete stmts;
|
|
|
|
|
}
|