Пример #1
0
void EditorInterface::makeIni()
{
	FNTRACE("", "EditorInterface", "makeIni", "");
	assert(!fileName.isEmpty());

	QFile iniFile(fileName+".ini");
	if (!iniFile.open(QIODevice::WriteOnly | QIODevice::Text))
		ETHROW(Exception(QString("Could not open %1 for writing.").arg(iniFile.fileName())));
	QTextStream iniOut(&iniFile);

	for (MapList::iterator mapIter = mapList.begin();
		mapIter != mapList.end(); ++mapIter)
	{
		iniOut << mapIter->typeId << ' ' << mapIter->prestDef << ' ' << mapIter->file << '\n';
	}
}
Пример #2
0
void IRGenerator::accept(Handler& handler)
{
    FNTRACE();

    setHandler(getHandler(handler.name()));
    setInsertPoint(createBlock("EntryPoint"));
    this->handler()->setEntryPoint(getInsertPoint());

    for (Symbol* symbol: *handler.scope()) {
        codegen(symbol);
    }

    codegen(handler.body());

    createRet(get(false));
}
Пример #3
0
std::unique_ptr<Stmt> FlowParser::postscriptStmt(std::unique_ptr<Stmt> baseStmt)
{
	FNTRACE();

	if (token() == FlowToken::Semicolon) {
		nextToken();
		return baseStmt;
	}

	if (baseStmt->location().end.line != lexer_->line())
		return baseStmt;

	FlowToken op = token();
	switch (op) {
		case FlowToken::If:
		case FlowToken::Unless:
			break;
		default:
			return baseStmt;
	}

	// STMT ['if' EXPR] ';'
	// STMT ['unless' EXPR] ';'

	FlowLocation sloc = location();

	nextToken(); // 'if' | 'unless'

	std::unique_ptr<Expr> condExpr = expr();
	if (!condExpr)
		return nullptr;

	consumeIf(FlowToken::Semicolon);

	if (op == FlowToken::Unless) {
        auto opc = makeOperator(FlowToken::Not, condExpr.get());
        if (opc == Opcode::EXIT) {
            reportError("Type cast error. No cast implementation found for requested cast from %s to %s.",
                    tos(condExpr->getType()).c_str(), "bool");
            return nullptr;
        }

		condExpr = std::make_unique<UnaryExpr>(opc, std::move(condExpr), sloc);
    }

	return std::make_unique<CondStmt>(std::move(condExpr), std::move(baseStmt), nullptr, sloc.update(end()));
}
Пример #4
0
void IRGenerator::accept(Handler& handlerSym)
{
    FNTRACE();

    assert(handlerStack_.empty());

    setHandler(getHandler(handlerSym.name()));
    setInsertPoint(createBlock("EntryPoint"));

    codegenInline(handlerSym);

    createRet(get(false));

    handler()->verify();

    assert(handlerStack_.empty());
}
Пример #5
0
void InitialConfigDialog::saveData()
{
	FNTRACE("", "InitialConfigDialog", "saveData", "");

	ini::AttributeMap data;
	lineedit("ds1editpath", editorPath, "", false, data);
	lineedit("ds1editname", editorName, "", false, data);

	// make sure file exists
	QFile iniFile("ds1edit_loader.ini");
	if (!iniFile.exists())
	{
		iniFile.open(QIODevice::ReadWrite | QIODevice::Text);
		iniFile.close();
	}
	ini::loader::writeData(data, ini::full);
}
Пример #6
0
void IRGenerator::accept(MatchStmt& stmt)
{
    FNTRACE();

    // TODO

    BasicBlock* contBlock = createBlock("match.cont");
    MatchInstr* matchInstr = new MatchInstr(stmt.op());

    Value* cond = codegen(stmt.condition());
    matchInstr->setCondition(cond);

    for (const MatchCase& one: stmt.cases()) {
        Value* label;
        if (auto e = dynamic_cast<StringExpr*>(one.first.get()))
            label = get(e->value());
        else if (auto e = dynamic_cast<RegExpExpr*>(one.first.get()))
            label = get(e->value());
        else {
            reportError("FIXME: Invalid (unsupported) literal type <%s> in match case.",
                    tos(one.first->getType()).c_str());
            result_ = nullptr;
            return;
        }

        BasicBlock* bb = createBlock("match.case");
        setInsertPoint(bb);
        codegen(one.second.get());
        createBr(contBlock);

        matchInstr->addCase(label, bb);
    }

    if (stmt.elseStmt()) {
        BasicBlock* elseBlock = createBlock("match.else");
        setInsertPoint(elseBlock);
        codegen(stmt.elseStmt());
        createBr(contBlock);

        matchInstr->setElseBlock(elseBlock);
    }

    setInsertPoint(contBlock);
}
Пример #7
0
void IRGenerator::accept(ArrayExpr& arrayExpr)
{
    FNTRACE();

    // loads a new array of given elements from regs[1] to regs[N], where regs[0] equals N;

    Value* array = createAlloca(arrayExpr.getType(), get(1 + arrayExpr.values().size()));

    // store array size at array[0]
    createArraySet(array, get(0), get(arrayExpr.values().size()));

    // store array values at array[1] to array[N]
    for (size_t i = 1, e = 1 + arrayExpr.values().size(); i != e; ++i) {
        Value* element = codegen(arrayExpr.values()[i].get());
        createArraySet(array, get(i), element);
    }

    result_ = array;
}
Пример #8
0
void EditorInterface::run()
{
	FNTRACE("", "EditorInterface", "run", "");
	assert(!editorProcess || editorProcess->state() == QProcess::NotRunning);

	if (!(QFileInfo(editorDir.filePath(editorName))).exists())
		ETHROW(Exception("The Loader can't find the Ds1 Editor. "
			"You must setup the Loader's ini to select where the Ds1 Editor .exe is. "
			"Use the menu \"Settings->Configure Loader\"."));

	QDir temp = QDir::temp();
	int i = 0;
	// find first tempX.ini that doesn't exist in temporary directory
	while (QFileInfo(temp.filePath(QString("temp%1.ini").arg(i))).exists())
		++i;

	if (!editorProcess)
		editorProcess = new QProcess(this);

	fileName = temp.filePath(QString("temp%1").arg(i));
	makeRelativePaths();
	QStringList args = makeArgs();

	output->clear();
	output->insertPlainText("ds1edit Loader: starting editor using program\n");
	output->insertPlainText(editorDir.filePath(editorName));
	output->insertPlainText("\nand arguments\n\"");
	output->insertPlainText(args.join("\" \""));

	connect(editorProcess, SIGNAL(finished(int, QProcess::ExitStatus)),
		SLOT(terminated(int, QProcess::ExitStatus)));
	connect(editorProcess, SIGNAL(readyReadStandardOutput()),
		SLOT(editorOutputReady()));

	editorProcess->setWorkingDirectory(editorDir.absolutePath());
	output->insertPlainText("\"\nStarting from directory: ");
	output->insertPlainText(editorProcess->workingDirectory());
	output->insertPlainText("\n\n");

	editorProcess->start(editorDir.filePath(editorName), args, QIODevice::ReadOnly | QIODevice::Text);
	//if (!editorProcess->waitForStarted())
	//	ETHROW(Exception("Editor process failed to start"));
}
Пример #9
0
void EditorInterface::makeRelativePaths()
{
	FNTRACE("", "EditorInterface", "makeRelativePaths", "");

	QString editorPath = editorDir.absolutePath();
	for (MapList::iterator mapIter = mapList.begin();
		mapIter != mapList.end(); ++mapIter)
	{
		if (mapIter->file.startsWith(editorPath))
			mapIter->file = mapIter->file.mid(editorPath.length()+1); // +1 for /
	}
	for (QStringList::iterator dt1Iter = dt1List.begin();
		dt1Iter != dt1List.end(); ++dt1Iter)
	{
		if (dt1Iter->startsWith(editorPath))
			(*dt1Iter) = dt1Iter->mid(editorPath.length()+1);
	}
	if (fileName.startsWith(editorPath))
		fileName = fileName.mid(editorPath.length()+1);
}
Пример #10
0
// }}}
// {{{ stmt
std::unique_ptr<Stmt> FlowParser::stmt()
{
	FNTRACE();

	switch (token()) {
		case FlowToken::If:
			return ifStmt();
		case FlowToken::Begin:
			return compoundStmt();
		case FlowToken::Ident:
			return callStmt();
		case FlowToken::Semicolon: {
			FlowLocation sloc(location());
			nextToken();
			return std::make_unique<CompoundStmt>(sloc.update(end()));
		}
		default:
			reportError("Unexpected token '%s'. Expected a statement instead.", token().c_str());
			return nullptr;
	}
}
Пример #11
0
void InitialConfigDialog::browseEditor()
{
	FNTRACE("", "InitialConfigDialog", "browseEditor", "");

	 QString executablePath =
		QFileDialog::getOpenFileName(this, "Select ds1edit executable",
			editorPath->text(), "Executable Files (*.exe);;All Files (*.*)");

	if (executablePath.length())
	{
		QFileInfo executable(executablePath);
		assert(executable.exists());
		editorPath->setText(executable.absolutePath());
		editorName->setText(executable.fileName());
	}

	if (!editorPath->text().isEmpty() && !editorName->text().isEmpty())
	{
		buttonBox->button(QDialogButtonBox::Ok)->setEnabled(true);
	}
}
Пример #12
0
void IRGenerator::accept(CondStmt& stmt)
{
    FNTRACE();

    BasicBlock* trueBlock = createBlock("trueBlock");
    BasicBlock* falseBlock = createBlock("falseBlock");
    BasicBlock* contBlock = createBlock("contBlock");

    Value* cond = codegen(stmt.condition());
    createCondBr(cond, trueBlock, falseBlock);

    setInsertPoint(trueBlock);
    codegen(stmt.thenStmt());
    createBr(contBlock);

    setInsertPoint(falseBlock);
    codegen(stmt.elseStmt());
    createBr(contBlock);

    setInsertPoint(contBlock);
}
Пример #13
0
EditorInterface::EditorInterface(LoaderDialog* dialog, const QString& path, const QString& name)
: editorDir(path), editorName(name), editorProcess(0)
{
	FNTRACE("", "EditorInterface", "EditorInterface", "LoaderDialog* dialog");
	assert(dialog->mapList->topLevelItemCount() > 0);

#define SYNCCHECKED(name) name = dialog-> name ->isChecked()
	SYNCCHECKED(resize);
	SYNCCHECKED(forceDt1);
	SYNCCHECKED(forcePalette);
	SYNCCHECKED(noCheckAct);
	SYNCCHECKED(autoPrestDef);
#undef SYNCCHECKED

#define GETNUMVAL(name) dialog-> name ->text().toInt()
	act = GETNUMVAL(forcePalAct);
	x = GETNUMVAL(resizeX);
	y = GETNUMVAL(resizeY);
#undef GETNUMVAL

	dt1List = dialog->dt1List;
	Ds1Info map;
	QTreeWidgetItem* item;
	for (int i = 0, itemCount = dialog->mapList->topLevelItemCount(); i < itemCount; ++i)
	{
		map.clear();
		item = dialog->mapList->topLevelItem(i);
		map.file = item->text(0);
		map.name = item->text(1);
		map.path = item->text(2);
		map.typeId = item->text(3).toInt();
		if (autoPrestDef)
			map.prestDef = -1;
		else
			map.prestDef = item->text(4).toInt();
		map.comment = item->text(5).toInt();
		mapList.append(map);
	}
	output = dialog->editorOutput;
}
Пример #14
0
	void readData(const QString& filename, AttributeMap& data) throw(ParseError, Exception)
	{
		FNTRACE("ini", "", "readData", QString("%1, %2 rows of data").arg(filename).arg(data.size()));

		QFile file(filename);
		if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
			ETHROW(Exception(QString("Unable to open %1 for reading.").arg(filename)));

		QByteArray line;
		size_t lineNumber = 0;

		while (!file.atEnd()) {

			line = file.readLine();
			++lineNumber;

			// trim comments and whitespace
			if (line.isEmpty()) continue;
			if (line.contains(COMMENT_BEGIN))
				line.truncate(line.indexOf(COMMENT_BEGIN));
			if (line.isEmpty()) continue;
			line = line.trimmed();
			if (line.isEmpty()) continue;

			// name=value pair?
			else if (line.contains(ASSIGNER))
			{
				QString name = line.left(line.indexOf(ASSIGNER));
				name = name.trimmed();
				if (name.isEmpty())
					ETHROW(ParseError(filename, lineNumber, "Empty name left of assigner."));
				QString value = line.right(line.length() - line.indexOf(ASSIGNER) - 1);
				value = value.trimmed();
				data[name] = value;
			}
			else
				ETHROW(ParseError(filename, lineNumber, "Unknown non-empty line."));
		}
	}
Пример #15
0
void EditorInterface::makeBatch(QString& batchFileName)
{
	FNTRACE("", "EditorInterface", "batchFileName", batchFileName);

	if (batchFileName.endsWith(".bat", Qt::CaseInsensitive))
		fileName = batchFileName.left(batchFileName.length()-4);
	else
		fileName = batchFileName;

	makeRelativePaths();

	batchFileName = fileName+".bat";
	QString debugFileName = fileName + "_debug.txt";

	QStringList args = makeArgs();

	QFile batchFile(batchFileName);
	if (!batchFile.open(QIODevice::WriteOnly | QIODevice::Text))
		ETHROW(Exception(QString("Failed to open %1 for writing").arg(batchFileName)));
	QTextStream batch(&batchFile);

	batch << "@echo off\n";
	if (QDir::drives().size()>1)
		batch << editorDir.absolutePath().left(2) << "\n";
	batch << "cd \"" << editorDir.absolutePath() << "\"\n" << editorName;
	for (QStringList::iterator arg = args.begin(); arg != args.end(); ++arg)
	{
		batch << ' ';
		if (arg->contains(' '))
			batch << '"'+(*arg)+'"';
		else
			batch << (*arg);
	}
	batch << " > \"" << debugFileName << "\"\n"
			"If ERRORLEVEL 0 goto DONE\n"
			"pause\n"
			":DONE\n";
}
Пример #16
0
void IRGenerator::accept(ArrayExpr& arrayExpr)
{
    FNTRACE();

    std::vector<Value*> values;
    for (size_t i = 0, e = arrayExpr.values().size(); i != e; ++i) {
        Value* element = codegen(arrayExpr.values()[i].get());
        values.push_back(element);
    }

    if (isConstant(values)) {
        std::vector<Constant*> constants;
        for (Value* value: values)
            constants.push_back(static_cast<Constant*>(value));

        result_ = get(constants);
    } else {
        // TODO: print line:col hint where this exact message occured.
        // via: reportError(arrayExpr, "Variable array elements not allowed.");
        reportError("Variable array elements not allowed.");
        result_ = nullptr;
    }
}
Пример #17
0
// handlerDecl ::= 'handler' IDENT (';' | [do] stmt)
std::unique_ptr<Handler> FlowParser::handlerDecl()
{
	FNTRACE();

	FlowLocation loc(location());
	nextToken(); // 'handler'

	consume(FlowToken::Ident);
	std::string name = stringValue();
	if (consumeIf(FlowToken::Semicolon)) { // forward-declaration
		loc.update(end());
		return std::make_unique<Handler>(name, loc);
	}

	std::unique_ptr<SymbolTable> st = enterScope("handler-" + name);
	std::unique_ptr<Stmt> body = stmt();
	leaveScope();

	if (!body)
		return nullptr;

	loc.update(body->location().end);

	// forward-declared / previousely -declared?
	if (Handler* handler = scope()->lookup<Handler>(name, Lookup::Self)) {
		if (handler->body() != nullptr) {
			// TODO say where we found the other hand, compared to this one.
			reportError("Redeclaring handler '%s'", handler->name().c_str());
			return nullptr;
		}
		handler->implement(std::move(st), std::move(body));
        handler->owner()->removeSymbol(handler);
        return std::unique_ptr<Handler>(handler);
	}

	return std::make_unique<Handler>(name, std::move(st), std::move(body), loc);
}
Пример #18
0
	void writeSparse(QFile& file, const AttributeMap& data)
	{
		FNTRACE("ini", "", "writeSparse", QString("file %1, %2 rows of data").arg(file.fileName()).arg(data.size()));

		if (!file.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate))
			ETHROW(Exception(QString("Unable to open %1 for writing.").arg(file.fileName())));

		file.resize(0);
		QTextStream fout(&file);

		int max_key_length = 0;
		for (AttributeMap::const_iterator iter = data.begin(); iter != data.end(); ++iter)
		{
			if (iter.key().length() > max_key_length)
				max_key_length = iter.key().length();
		}
		for (AttributeMap::const_iterator iter = data.begin(); iter != data.end(); ++iter)
		{
			fout << iter.key();
			for (int i = iter.key().length(); i < max_key_length; ++i)
				fout << ' ';
			fout << " = " << iter.value() << "\n";
		}
	}
Пример #19
0
// primaryExpr ::= NUMBER
//               | STRING
//               | variable
//               | function '(' exprList ')'
//               | '(' expr ')'
std::unique_ptr<Expr> FlowParser::primaryExpr()
{
	FNTRACE();

	static struct {
		const char* ident;
		long long nominator;
		long long denominator;
	} units[] = {
		{ "byte", 1, 1 },
		{ "kbyte", 1024llu, 1 },
		{ "mbyte", 1024llu * 1024, 1 },
		{ "gbyte", 1024llu * 1024 * 1024, 1 },
		{ "tbyte", 1024llu * 1024 * 1024 * 1024, 1 },
		{ "bit", 1, 8 },
		{ "kbit", 1024llu, 8 },
		{ "mbit", 1024llu * 1024, 8 },
		{ "gbit", 1024llu * 1024 * 1024, 8 },
		{ "tbit", 1024llu * 1024 * 1024 * 1024, 8 },
		{ "sec", 1, 1 },
		{ "min", 60llu, 1 },
		{ "hour", 60llu * 60, 1 },
		{ "day", 60llu * 60 * 24, 1 },
		{ "week", 60llu * 60 * 24 * 7, 1 },
		{ "month", 60llu * 60 * 24 * 30, 1 },
		{ "year", 60llu * 60 * 24 * 365, 1 },
		{ nullptr, 1, 1 }
	};

	FlowLocation loc(location());

	switch (token()) {
		case FlowToken::Ident: {
			std::string name = stringValue();
			nextToken();

			Symbol* symbol = scope()->lookup(name, Lookup::All);
			if (!symbol) {
                // XXX assume that given symbol is a auto forward-declared handler.
                Handler* href = (Handler*) globalScope()->appendSymbol(std::make_unique<Handler>(name, loc));
				return std::make_unique<HandlerRefExpr>(href, loc);
			}

			if (auto variable = dynamic_cast<Variable*>(symbol))
				return std::make_unique<VariableExpr>(variable, loc);

			if (auto handler = dynamic_cast<Handler*>(symbol))
				return std::make_unique<HandlerRefExpr>(handler, loc);

			if (symbol->type() == Symbol::BuiltinFunction) {
				if (token() != FlowToken::RndOpen)
					return std::make_unique<FunctionCallExpr>((BuiltinFunction*) symbol, ExprList()/*args*/, loc);

				nextToken();
                ExprList args;
				bool rv = listExpr(args);
				consume(FlowToken::RndClose);
				if (!rv) return nullptr;
				return std::make_unique<FunctionCallExpr>((BuiltinFunction*) symbol, std::move(args), loc);
			}

			reportError("Unsupported symbol type of '%s' in expression.", name.c_str());
			return nullptr;
		}
		case FlowToken::Boolean: {
			std::unique_ptr<BoolExpr> e = std::make_unique<BoolExpr>(booleanValue(), loc);
			nextToken();
			return std::move(e);
		}
		case FlowToken::RegExp: {
			std::unique_ptr<RegExpExpr> e = std::make_unique<RegExpExpr>(RegExp(stringValue()), loc);
			nextToken();
			return std::move(e);
		}
		case FlowToken::InterpolatedStringFragment:
			return interpolatedStr();
		case FlowToken::String:
		case FlowToken::RawString: {
			std::unique_ptr<StringExpr> e = std::make_unique<StringExpr>(stringValue(), loc);
			nextToken();
			return std::move(e);
		}
		case FlowToken::Number: { // NUMBER [UNIT]
			auto number = numberValue();
			nextToken();

			if (token() == FlowToken::Ident) {
				std::string sv(stringValue());
				for (size_t i = 0; units[i].ident; ++i) {
					if (sv == units[i].ident
						|| (sv[sv.size() - 1] == 's' && sv.substr(0, sv.size() - 1) == units[i].ident))
					{
						nextToken(); // UNIT
						number = number * units[i].nominator / units[i].denominator;
						loc.update(end());
						break;
					}
				}
			}
			return std::make_unique<NumberExpr>(number, loc);
		}
		case FlowToken::IP: {
			std::unique_ptr<IPAddressExpr> e = std::make_unique<IPAddressExpr>(lexer_->ipValue(), loc);
			nextToken();
			return std::move(e);
		}
		case FlowToken::Cidr: {
			std::unique_ptr<CidrExpr> e = std::make_unique<CidrExpr>(lexer_->cidr(), loc);
			nextToken();
			return std::move(e);
		}
		case FlowToken::StringType:
		case FlowToken::NumberType:
		case FlowToken::BoolType:
			return castExpr();
		case FlowToken::Begin: { // lambda-like inline function ref
			char name[64];
			static unsigned long i = 0;
            ++i;
			snprintf(name, sizeof(name), "__lambda_%lu", i);

			FlowLocation loc = location();
			auto st = std::make_unique<SymbolTable>(scope(), name);
			enter(st.get());
			std::unique_ptr<Stmt> body = compoundStmt();
			leave();

			if (!body)
				return nullptr;

			loc.update(body->location().end);

			Handler* handler = new Handler(name, std::move(st), std::move(body), loc);
			// TODO (memory leak): add handler to unit's global scope, i.e. via:
			//       - scope()->rootScope()->insert(handler);
			//       - unit_->scope()->insert(handler);
			//       to get free'd
			return std::make_unique<HandlerRefExpr>(handler, loc);
		}
		case FlowToken::RndOpen: {
			nextToken();
			std::unique_ptr<Expr> e = expr();
			consume(FlowToken::RndClose);
			e->setLocation(loc.update(end()));
			return e;
		}
		default:
			TRACE(1, "Expected primary expression. Got something... else.");
			reportUnexpectedToken();
			return nullptr;
	}
}
Пример #20
0
	void writePreserving(QFile& inFile, QTextStream& out, const AttributeMap& data)
	{
		FNTRACE("ini", "", "writePreserving", QString("in, out, %1 rows of data").arg(data.size()));

		int i, j;
		QChar c;
		QString name;
		size_t lineNumber = 0;
		QString line;
		typedef QSet<AttributeMap::key_type> KeySet;
		KeySet unwrittenKeys = KeySet::fromList(data.keys());

		if (!inFile.open(QIODevice::ReadOnly | QIODevice::Text))
			ETHROW(Exception(QString("Unable to open %1 for reading.").arg(inFile.fileName())));
		QTextStream in(&inFile);

		while (!(line = in.readLine()).isNull())
		{
			++lineNumber;
			//std::cout << lineNumber << ": " << line.toStdString() << ":\n";

			for (i = 0; line[i].isSpace(); ++i) { out << line[i]; }

			if (line[i].isNull()) { out << '\n'; continue; }
			else if (line[i] == COMMENT_BEGIN) { out << line.mid(i) << '\n'; continue; }

			for (j = i; !(c = line[i]).isNull() && c!=COMMENT_BEGIN && c!=ASSIGNER; ++i) ;
			//std::cout << "non-empty, ";
			if (c != ASSIGNER) // non-empty line that isn't assignment -> invalid
				ETHROW(ParseError(inFile.fileName(), lineNumber, "Unknown non-empty line."));
			for (--i; line[i].isSpace(); --i) ; // last character of name
			name = line.mid(j, i - j + 1);
			//std::cout << "name: " << name.toStdString() << ' ';

			for ( ; line[j]!=ASSIGNER; ++j) out << line[j];
			out << ASSIGNER;
			i = j + 1;

			for ( ; line[i].isSpace(); ++i) out << line[i];

			if (data.contains(name))
			{
				//std::cout << "known ";
				out << data.value(name);
				unwrittenKeys.remove(name);
				for (j = i; !line[i].isNull() && line[i]!=COMMENT_BEGIN; ++i) ; // EOL || comment
				for (--i; line[i].isSpace(); --i) ; // last character of value
				++i; // first character after value
			}

			out << line.mid(i) << '\n';
			//std::cout << '\n';
		}

		if (unwrittenKeys.size())
		{
			out << '\n' << COMMENT_BEGIN << "Following lines were generated by Ds1edit Loader:\n";
			for (KeySet::iterator key = unwrittenKeys.begin();
				key != unwrittenKeys.end(); ++key)
				out << (*key) << ' ' << ASSIGNER << ' ' << data.value(*key) << '\n';
		}

		//in.resize(in.pos()+1);
		inFile.close();
	}
Пример #21
0
void IRGenerator::accept(ExprStmt& stmt)
{
    FNTRACE();

    codegen(stmt.expression());
}
Пример #22
0
void IRGenerator::accept(BinaryExpr& expr)
{
    FNTRACE();

    static const std::unordered_map<
        int /*FlowVM::Opcode*/,
        Value* (IRGenerator::*)(Value*, Value*, const std::string&)
    > ops = {
        // numerical
        { FlowVM::Opcode::NADD, &IRGenerator::createAdd },
        { FlowVM::Opcode::NSUB, &IRGenerator::createSub },
        { FlowVM::Opcode::NMUL, &IRGenerator::createMul },
        { FlowVM::Opcode::NDIV, &IRGenerator::createDiv },
        { FlowVM::Opcode::NREM, &IRGenerator::createRem },
        { FlowVM::Opcode::NSHL, &IRGenerator::createShl },
        { FlowVM::Opcode::NSHR, &IRGenerator::createShr },
        { FlowVM::Opcode::NPOW, &IRGenerator::createPow },
        { FlowVM::Opcode::NAND, &IRGenerator::createAnd },
        { FlowVM::Opcode::NOR,  &IRGenerator::createOr },
        { FlowVM::Opcode::NXOR, &IRGenerator::createXor },
        { FlowVM::Opcode::NCMPEQ, &IRGenerator::createNCmpEQ },
        { FlowVM::Opcode::NCMPNE, &IRGenerator::createNCmpNE },
        { FlowVM::Opcode::NCMPLE, &IRGenerator::createNCmpLE },
        { FlowVM::Opcode::NCMPGE, &IRGenerator::createNCmpGE },
        { FlowVM::Opcode::NCMPLT, &IRGenerator::createNCmpLT },
        { FlowVM::Opcode::NCMPGT, &IRGenerator::createNCmpGT },

        // string
        { FlowVM::Opcode::SADD, &IRGenerator::createSAdd },
        { FlowVM::Opcode::SCMPEQ, &IRGenerator::createSCmpEQ },
        { FlowVM::Opcode::SCMPNE, &IRGenerator::createSCmpNE },
        { FlowVM::Opcode::SCMPLE, &IRGenerator::createSCmpLE },
        { FlowVM::Opcode::SCMPGE, &IRGenerator::createSCmpGE },
        { FlowVM::Opcode::SCMPLT, &IRGenerator::createSCmpLT },
        { FlowVM::Opcode::SCMPGT, &IRGenerator::createSCmpGT },
        { FlowVM::Opcode::SCMPBEG, &IRGenerator::createSCmpEB },
        { FlowVM::Opcode::SCMPEND, &IRGenerator::createSCmpEE },
        { FlowVM::Opcode::SCONTAINS, &IRGenerator::createSIn },

        // regex
        { FlowVM::Opcode::SREGMATCH, &IRGenerator::createSCmpRE },

        // ip
        { FlowVM::Opcode::PCMPEQ, &IRGenerator::createPCmpEQ },
        { FlowVM::Opcode::PCMPNE, &IRGenerator::createPCmpNE },
        { FlowVM::Opcode::PINCIDR, &IRGenerator::createPInCidr },
    };

    if (expr.op() == FlowVM::Opcode::BOR) {
        // (lhs || rhs)
        //
        //   L = lhs();
        //   if (L) goto end;
        //   R = rhs();
        //   L = R;
        // end:
        //   result = L;

        BasicBlock* borLeft = createBlock("bor.left");
        BasicBlock* borRight = createBlock("bor.right");
        BasicBlock* borCont = createBlock("bor.cont");

        AllocaInstr* result = createAlloca(FlowType::Boolean, get(1), "bor");
        Value* lhs = codegen(expr.leftExpr());
        createCondBr(lhs, borLeft, borRight);

        setInsertPoint(borLeft);
        createStore(result, lhs, "bor.left");
        createBr(borCont);

        setInsertPoint(borRight);
        Value* rhs = codegen(expr.rightExpr());
        createStore(result, rhs, "bor.right");
        createBr(borCont);

        setInsertPoint(borCont);

        result_ = result;

        return;
    }

    Value* lhs = codegen(expr.leftExpr());
    Value* rhs = codegen(expr.rightExpr());

    auto i = ops.find(expr.op());
    if (i != ops.end()) {
        result_ = (this->*i->second)(lhs, rhs, "");
    } else {
        fprintf(stderr, "BUG: Binary operation `%s` not implemented.\n", mnemonic(expr.op()));
        assert(!"Unimplemented");
        result_ = nullptr;
    }
}
Пример #23
0
void IRGenerator::accept(BuiltinHandler& builtin)
{
    FNTRACE();

    result_ = getBuiltinHandler(builtin.signature());
}
Пример #24
0
void IRGenerator::accept(BuiltinFunction& builtin)
{
    FNTRACE();

    result_ = getBuiltinFunction(builtin.signature());
}
Пример #25
0
std::unique_ptr<Stmt> FlowParser::callStmt()
{
	// callStmt ::= NAME ['(' exprList ')' | exprList] (';' | LF)
	// 			 | NAME '=' expr [';' | LF]
	// NAME may be a builtin-function, builtin-handler, handler-name, or variable.

	FNTRACE();

	FlowLocation loc(location());
	std::string name = stringValue();
	nextToken(); // IDENT

	std::unique_ptr<Stmt> stmt;
	Symbol* callee = scope()->lookup(name, Lookup::All);
	if (!callee) {
        // XXX assume that given symbol is a auto forward-declared handler.
        callee = (Handler*) globalScope()->appendSymbol(std::make_unique<Handler>(name, loc));
	}

	bool callArgs = false;
	switch (callee->type()) {
		case Symbol::Variable: { // var '=' expr (';' | LF)
			if (!consume(FlowToken::Assign))
				return nullptr;

			std::unique_ptr<Expr> value = expr();
			if (!value)
				return nullptr;

			stmt = std::make_unique<AssignStmt>(static_cast<Variable*>(callee), std::move(value), loc.update(end()));
			break;
		}
		case Symbol::BuiltinHandler:
		case Symbol::BuiltinFunction:
			stmt = std::make_unique<CallStmt>(loc, (Callable*) callee);
			callArgs = true;
			break;
		case Symbol::Handler:
			stmt = std::make_unique<CallStmt>(loc, (Callable*) callee);
            break;
		default:
			break;
	}

	if (callArgs) {
		CallStmt* callStmt = static_cast<CallStmt*>(stmt.get());

		if (token() == FlowToken::RndOpen) {
			nextToken();
            ExprList args;
			bool rv = listExpr(args);
			consume(FlowToken::RndClose);
			if (!rv) return nullptr;
			callStmt->setArgs(std::move(args));
		}
		else if (lexer_->line() == loc.begin.line) {
            ExprList args;
			if (!listExpr(args))
                return nullptr;
			callStmt->setArgs(std::move(args));
		}

        // match call parameters
        FlowVM::Signature sig;
        sig.setName(name);
        sig.setReturnType(callStmt->callee()->signature().returnType()); // XXX cheetah
        std::vector<FlowType> argTypes;
        for (const auto& arg: callStmt->args()) {
            argTypes.push_back(arg->getType());
        }
        sig.setArgs(argTypes);
        if (sig != callStmt->callee()->signature()) {
            reportError("Callee parameter type signature mismatch: %s passed, but %s expected.\n", 
                    sig.to_s().c_str(), callStmt->callee()->signature().to_s().c_str());
            return nullptr;
        }
	}

	switch (token()) {
		case FlowToken::If:
		case FlowToken::Unless:
			return postscriptStmt(std::move(stmt));
		case FlowToken::Semicolon:
			// stmt ';'
			nextToken();
			stmt->location().update(end());
			return stmt;
		default:
			if (stmt->location().end.line != lexer_->line())
				return stmt;

			reportUnexpectedToken();
			return nullptr;
	}
}