2014-11-29 00:47:50 +01:00
|
|
|
/*
|
|
|
|
* Monicelli: as esoteric language compiler
|
|
|
|
*
|
|
|
|
* Copyright (C) 2014 Stefano Sanfilippo
|
|
|
|
*
|
|
|
|
* This program is free software: you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
|
2014-11-27 20:01:06 +01:00
|
|
|
#include "Nodes.hpp"
|
|
|
|
|
|
|
|
using namespace monicelli;
|
|
|
|
|
|
|
|
static const std::string BLOCK = " ";
|
|
|
|
|
2014-11-28 20:18:50 +01:00
|
|
|
std::ostream& monicelli::operator<<(std::ostream &stream, const Type &type) {
|
|
|
|
switch (type) {
|
|
|
|
case Type::INT:
|
|
|
|
stream << "int";
|
|
|
|
break;
|
|
|
|
case Type::CHAR:
|
|
|
|
stream << "char";
|
|
|
|
break;
|
|
|
|
case Type::FLOAT:
|
|
|
|
stream << "float";
|
|
|
|
break;
|
|
|
|
case Type::BOOL:
|
|
|
|
stream << "bool";
|
|
|
|
break;
|
|
|
|
case Type::DOUBLE:
|
|
|
|
stream << "double";
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return stream;
|
|
|
|
}
|
|
|
|
|
2014-11-27 20:01:06 +01:00
|
|
|
void emitIndent(std::ostream &stream, int indent) {
|
|
|
|
for (int i = 0; i < indent; ++i) {
|
|
|
|
stream << BLOCK;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Id::emit(std::ostream &stream, int indent) {
|
2014-11-28 00:01:24 +01:00
|
|
|
stream << *value;
|
2014-11-27 20:01:06 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void Integer::emit(std::ostream &stream, int indent) {
|
|
|
|
stream << value;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Float::emit(std::ostream &stream, int indent) {
|
|
|
|
stream << value;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ExpNode::emit(std::ostream &stream, int indent) {
|
|
|
|
left->emit(stream);
|
|
|
|
stream << ' ' << getSym() << ' ';
|
|
|
|
right->emit(stream);
|
|
|
|
}
|
|
|
|
|
|
|
|
void SemiExpNode::emit(std::ostream &stream, int indent) {
|
2014-11-27 21:51:20 +01:00
|
|
|
SimpleExpression *e = dynamic_cast<SimpleExpression*>(left.get());
|
2014-11-27 20:01:06 +01:00
|
|
|
bool braces = (e == nullptr);
|
|
|
|
|
|
|
|
stream << ' ' << getSym() << ' ';
|
|
|
|
if (braces) stream << "(";
|
|
|
|
left->emit(stream);
|
|
|
|
if (braces) stream << ")";
|
|
|
|
}
|
|
|
|
|
|
|
|
void StatementList::emit(std::ostream &stream, int indent) {
|
|
|
|
for (Statement *s: *this) {
|
|
|
|
emitIndent(stream, indent);
|
|
|
|
s->emit(stream, indent);
|
|
|
|
stream << ";\n";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Return::emit(std::ostream &stream, int indent) {
|
|
|
|
stream << "return";
|
|
|
|
|
|
|
|
if (expression != nullptr) {
|
|
|
|
stream << ' ';
|
|
|
|
expression->emit(stream);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Loop::emit(std::ostream &stream, int indent) {
|
|
|
|
stream << "do {\n";
|
|
|
|
|
|
|
|
body->emit(stream, indent + 1);
|
|
|
|
|
|
|
|
emitIndent(stream, indent);
|
|
|
|
stream << "} while (";
|
|
|
|
condition->emit(stream);
|
|
|
|
stream << ")";
|
|
|
|
}
|
|
|
|
|
|
|
|
void BranchCase::emit(std::ostream &stream, int indent) {
|
|
|
|
condition->emit(stream);
|
|
|
|
stream << ") {\n";
|
|
|
|
body->emit(stream, indent);
|
|
|
|
emitIndent(stream, indent - 1);
|
|
|
|
stream << "}";
|
|
|
|
}
|
|
|
|
|
|
|
|
void Branch::emit(std::ostream &stream, int indent) {
|
|
|
|
stream << "if (";
|
|
|
|
var->emit(stream);
|
|
|
|
|
|
|
|
if (cases->size() > 0) {
|
|
|
|
BranchCase *last = cases->back();
|
|
|
|
for (BranchCase *c: *cases) {
|
|
|
|
c->emit(stream, indent + 1);
|
|
|
|
if (c != last) {
|
|
|
|
stream << " else if (";
|
|
|
|
var->emit(stream);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-11-28 20:19:19 +01:00
|
|
|
if (els == nullptr) {
|
|
|
|
return;
|
2014-11-27 22:10:10 +01:00
|
|
|
}
|
2014-11-28 20:19:19 +01:00
|
|
|
|
|
|
|
stream << " else {\n";
|
|
|
|
els->emit(stream, indent + 1);
|
|
|
|
emitIndent(stream, indent);
|
|
|
|
stream << "}";
|
2014-11-27 20:01:06 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void VarDeclaration::emit(std::ostream &stream, int indent) {
|
2014-11-28 20:18:50 +01:00
|
|
|
stream << type << ' ';
|
2014-11-27 20:01:06 +01:00
|
|
|
if (point) stream << '*';
|
|
|
|
name->emit(stream);
|
|
|
|
|
|
|
|
if (init != nullptr) {
|
|
|
|
stream << " = ";
|
|
|
|
init->emit(stream);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Assignment::emit(std::ostream &stream, int indent) {
|
|
|
|
name->emit(stream);
|
|
|
|
stream << " = ";
|
|
|
|
value->emit(stream);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Print::emit(std::ostream &stream, int indent) {
|
|
|
|
stream << "std::cout << ";
|
|
|
|
expression->emit(stream);
|
2014-11-27 21:20:50 +01:00
|
|
|
stream << " << std::endl";
|
2014-11-27 20:01:06 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void Input::emit(std::ostream &stream, int indent) {
|
|
|
|
stream << "std::cin >> ";
|
|
|
|
variable->emit(stream);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Abort::emit(std::ostream &stream, int indent) {
|
|
|
|
stream << "std::exit(1)";
|
|
|
|
}
|
|
|
|
|
|
|
|
void Assert::emit(std::ostream &stream, int indent) {
|
|
|
|
stream << "std::assert(";
|
|
|
|
expression->emit(stream);
|
|
|
|
stream << ")";
|
|
|
|
}
|
|
|
|
|
|
|
|
void FunctionCall::emit(std::ostream &stream, int indent) {
|
|
|
|
name->emit(stream);
|
|
|
|
stream << "(";
|
|
|
|
args->emit(stream);
|
|
|
|
stream << ")";
|
|
|
|
}
|
|
|
|
|
|
|
|
void Function::emit(std::ostream &stream, int indent) {
|
|
|
|
emitIndent(stream, indent);
|
|
|
|
|
|
|
|
stream << "void ";
|
|
|
|
name->emit(stream);
|
|
|
|
stream << "(";
|
|
|
|
args->emit(stream);
|
|
|
|
stream << ") {\n";
|
|
|
|
body->emit(stream, indent + 1);
|
2014-11-27 20:43:09 +01:00
|
|
|
stream << "}\n\n";
|
2014-11-27 20:01:06 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void Main::emit(std::ostream &stream, int indent) {
|
|
|
|
emitIndent(stream, indent);
|
|
|
|
|
|
|
|
stream << "int main() {\n";
|
|
|
|
body->emit(stream, indent + 1);
|
|
|
|
stream << "}\n";
|
|
|
|
}
|
|
|
|
|
|
|
|
void Program::emit(std::ostream &stream, int indent) {
|
2014-11-27 20:43:25 +01:00
|
|
|
stream << "#include <iostream>\n";
|
|
|
|
stream << "#include <cstdlib>\n\n";
|
|
|
|
|
2014-11-27 20:01:06 +01:00
|
|
|
for (Function *f: functions) {
|
|
|
|
f->emit(stream);
|
|
|
|
}
|
|
|
|
|
2014-11-27 22:10:10 +01:00
|
|
|
if (main != nullptr) {
|
|
|
|
main->emit(stream);
|
|
|
|
}
|
2014-11-27 20:01:06 +01:00
|
|
|
}
|
|
|
|
|