2013-05-31 19:04:25 +02:00
|
|
|
/* The scully programming language.
|
|
|
|
|
*
|
|
|
|
|
* Copyright (c) Peter Dahlberg, Markus Hauschild and Florian Sattler, 2013.
|
|
|
|
|
* Licensed under the GNU GPL v2.
|
|
|
|
|
*/
|
|
|
|
|
|
2013-05-31 23:51:44 +02:00
|
|
|
#include "Token.h"
|
|
|
|
|
|
2013-06-01 14:32:48 +02:00
|
|
|
#include "AST/CodeGenVisitor.h"
|
|
|
|
|
|
2013-06-01 14:29:18 +02:00
|
|
|
#include "llvm/DerivedTypes.h"
|
|
|
|
|
#include "llvm/ExecutionEngine/ExecutionEngine.h"
|
|
|
|
|
#include "llvm/ExecutionEngine/JIT.h"
|
|
|
|
|
#include "llvm/IRBuilder.h"
|
|
|
|
|
#include "llvm/LLVMContext.h"
|
|
|
|
|
#include "llvm/Module.h"
|
|
|
|
|
#include "llvm/PassManager.h"
|
|
|
|
|
#include "llvm/Analysis/Verifier.h"
|
|
|
|
|
#include "llvm/Analysis/Passes.h"
|
|
|
|
|
#include "llvm/DataLayout.h"
|
|
|
|
|
#include "llvm/Transforms/Scalar.h"
|
|
|
|
|
#include "llvm/Support/TargetSelect.h"
|
|
|
|
|
|
2013-05-31 21:35:44 +02:00
|
|
|
// this file is auto generated from grammar/grammar.y
|
2013-05-31 22:20:31 +02:00
|
|
|
#include "grammar.h"
|
2013-05-31 21:35:44 +02:00
|
|
|
|
|
|
|
|
#include "lexertl/generator.hpp"
|
|
|
|
|
#include "lexertl/lookup.hpp"
|
|
|
|
|
#include "lexertl/rules.hpp"
|
|
|
|
|
#include "lexertl/state_machine.hpp"
|
|
|
|
|
|
2013-05-31 19:04:25 +02:00
|
|
|
int main() {
|
2013-06-01 22:36:15 +02:00
|
|
|
srand(42);
|
|
|
|
|
|
2013-06-01 23:51:43 +02:00
|
|
|
bool debugParser = true;
|
|
|
|
|
bool debugCodeGen = true;
|
2013-06-01 23:26:43 +02:00
|
|
|
|
2013-05-31 22:20:31 +02:00
|
|
|
lexertl::rules rules;
|
|
|
|
|
lexertl::state_machine state_machine;
|
|
|
|
|
|
|
|
|
|
//keywords
|
|
|
|
|
rules.add("bool", T_BOOL);
|
|
|
|
|
rules.add("for", T_FOR);
|
|
|
|
|
rules.add("if", T_IF);
|
|
|
|
|
rules.add("int", T_INT);
|
|
|
|
|
rules.add("return", T_RETURN);
|
|
|
|
|
rules.add("void", T_VOID);
|
|
|
|
|
rules.add("rfor", T_RFOR);
|
|
|
|
|
rules.add("rif", T_RIF);
|
2013-06-02 08:31:45 +02:00
|
|
|
//rules.add("string", T_STRING);
|
2013-05-31 22:20:31 +02:00
|
|
|
|
|
|
|
|
// special characters
|
2013-06-01 22:36:15 +02:00
|
|
|
//rules.add("\"(\"", T_LPAREN);
|
|
|
|
|
//rules.add("\")\"", T_RPAREN);
|
|
|
|
|
rules.add("dana", T_LPAREN);
|
|
|
|
|
rules.add("fox", T_RPAREN);
|
2013-05-31 22:20:31 +02:00
|
|
|
rules.add("mulder", T_BEGIN);
|
|
|
|
|
rules.add("scully", T_END);
|
|
|
|
|
rules.add(",", T_COMMA);
|
|
|
|
|
rules.add(";", T_SEMICOLON);
|
|
|
|
|
|
|
|
|
|
// operators
|
|
|
|
|
rules.add("=", T_ASSIGN);
|
|
|
|
|
rules.add("==", T_EQUALS);
|
|
|
|
|
rules.add("<", T_LESS);
|
|
|
|
|
rules.add("\"+\"", T_PLUS);
|
|
|
|
|
rules.add("\"-\"", T_MINUS);
|
|
|
|
|
rules.add("\"*\"", T_TIMES);
|
|
|
|
|
rules.add("\"/\"", T_DIV);
|
|
|
|
|
|
|
|
|
|
// constants
|
|
|
|
|
rules.add("true", T_TRUE);
|
|
|
|
|
rules.add("false", T_FALSE);
|
|
|
|
|
rules.add("\\d+", T_CINT);
|
|
|
|
|
|
|
|
|
|
// identifier
|
|
|
|
|
rules.add("[a-zA-Z_][a-zA-Z_0-9]*", T_IDENTIFIER);
|
|
|
|
|
|
|
|
|
|
// whitespace
|
|
|
|
|
rules.add("\\s+", T_WHITESPACE);
|
|
|
|
|
|
|
|
|
|
lexertl::generator::build(rules, state_machine);
|
|
|
|
|
state_machine.minimise();
|
|
|
|
|
|
2013-06-01 14:29:18 +02:00
|
|
|
std::cout << "The scully programming language v0.2" << std::endl;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Setup LLVM JIT
|
|
|
|
|
llvm::InitializeNativeTarget();
|
|
|
|
|
llvm::Module* module = new llvm::Module("SCULLY/JIT", llvm::getGlobalContext());
|
|
|
|
|
std::string errStr;
|
|
|
|
|
llvm::ExecutionEngine* ee = llvm::EngineBuilder(module).setErrorStr(&errStr).create();
|
|
|
|
|
if (!ee) {
|
|
|
|
|
std::cerr << "Error creating Execution Engine: " << errStr << std::endl;
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Set up the optimizer pipeline. Start with registering info about how the
|
|
|
|
|
// target lays out data structures.
|
|
|
|
|
llvm::FunctionPassManager* fpm = new llvm::FunctionPassManager(module);
|
|
|
|
|
|
|
|
|
|
fpm->add(new llvm::DataLayout(*ee->getDataLayout()));
|
|
|
|
|
// Provide basic AliasAnalysis support for GVN.
|
|
|
|
|
fpm->add(llvm::createBasicAliasAnalysisPass());
|
|
|
|
|
// Do simple "peephole" optimizations and bit-twiddling optzns.
|
|
|
|
|
fpm->add(llvm::createInstructionCombiningPass());
|
|
|
|
|
// Reassociate expressions.
|
|
|
|
|
fpm->add(llvm::createReassociatePass());
|
|
|
|
|
// Eliminate Common SubExpressions.
|
|
|
|
|
fpm->add(llvm::createGVNPass());
|
|
|
|
|
// Simplify the control flow graph (deleting unreachable blocks, etc).
|
|
|
|
|
fpm->add(llvm::createCFGSimplificationPass());
|
|
|
|
|
|
|
|
|
|
fpm->doInitialization();
|
|
|
|
|
|
2013-06-01 21:10:05 +02:00
|
|
|
CodeGenVisitor* cv = new CodeGenVisitor(module, fpm, ee);
|
2013-05-31 22:20:31 +02:00
|
|
|
|
2013-05-31 23:51:44 +02:00
|
|
|
void* parser = scullyParserAlloc(malloc);
|
|
|
|
|
|
2013-05-31 22:20:31 +02:00
|
|
|
while (true) {
|
|
|
|
|
std::cout << "> ";
|
|
|
|
|
std::string input;
|
|
|
|
|
std::getline(std::cin, input);
|
|
|
|
|
if (std::cin.eof()) {
|
|
|
|
|
std::cout << std::endl << "Bye." << std::endl;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2013-06-01 23:26:43 +02:00
|
|
|
if (input == "@dp") {
|
|
|
|
|
debugParser = !debugParser;
|
|
|
|
|
std::cout << "Debugging for the parser: " << debugParser << std::endl;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (input == "@dc") {
|
|
|
|
|
debugCodeGen = !debugCodeGen;
|
|
|
|
|
std::cout << "Debugging for the code generation: " << debugCodeGen << std::endl;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
2013-05-31 22:20:31 +02:00
|
|
|
auto iter = input.begin();
|
|
|
|
|
auto end = input.end();
|
|
|
|
|
lexertl::smatch results(iter, end);
|
|
|
|
|
|
|
|
|
|
do {
|
|
|
|
|
lexertl::lookup (state_machine, results);
|
|
|
|
|
std::string s(results.start, results.end);
|
|
|
|
|
if (results.id != T_WHITESPACE) {
|
2013-06-01 18:32:04 +02:00
|
|
|
//std::cout << "Id: " << results.id << ", Token: " << s << std::endl;
|
2013-06-01 22:36:15 +02:00
|
|
|
try {
|
|
|
|
|
scullyParser(parser, results.id, new Token(s), cv);
|
|
|
|
|
} catch (const char* c) {
|
|
|
|
|
std::cerr << "Error: " << c << std::endl;
|
|
|
|
|
}
|
2013-05-31 22:20:31 +02:00
|
|
|
}
|
|
|
|
|
} while (results.id != 0);
|
2013-06-01 14:29:18 +02:00
|
|
|
|
2013-06-01 23:26:43 +02:00
|
|
|
if (debugCodeGen) {
|
|
|
|
|
module->dump();
|
|
|
|
|
}
|
2013-05-31 22:20:31 +02:00
|
|
|
}
|
2013-05-31 23:51:44 +02:00
|
|
|
|
|
|
|
|
scullyParserFree(parser, free);
|
2013-05-31 22:20:31 +02:00
|
|
|
return 0;
|
2013-05-31 19:04:25 +02:00
|
|
|
}
|