Merge branch 'location'
This commit is contained in:
commit
8aa5c1a575
|
@ -71,7 +71,10 @@ llvm::AllocaInst* allocateReturnVariable(llvm::Function *func) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
bool reportError(std::initializer_list<std::string> const& what) {
|
bool reportError(Localizable const& node, std::initializer_list<std::string> const& what) {
|
||||||
|
std::cerr << "line " << node.getLocation().begin.line << ", ";
|
||||||
|
std::cerr << "col " << node.getLocation().begin.column << ": ";
|
||||||
|
|
||||||
for (std::string const& chunk: what) {
|
for (std::string const& chunk: what) {
|
||||||
std::cerr << chunk << ' ';
|
std::cerr << chunk << ' ';
|
||||||
}
|
}
|
||||||
|
@ -307,7 +310,7 @@ bool BitcodeEmitter::emit(VarDeclaration const& node) {
|
||||||
if (node.getInitializer()) {
|
if (node.getInitializer()) {
|
||||||
GUARDED(node.getInitializer()->emit(this));
|
GUARDED(node.getInitializer()->emit(this));
|
||||||
if (!convertAndStore(d, alloc, d->retval)) {
|
if (!convertAndStore(d, alloc, d->retval)) {
|
||||||
return reportError({
|
return reportError(node, {
|
||||||
"Invalid inizializer for variable", node.getId().getValue()
|
"Invalid inizializer for variable", node.getId().getValue()
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -324,14 +327,15 @@ bool BitcodeEmitter::emit(Assignment const& node) {
|
||||||
auto var = d->scope.lookup(node.getName().getValue());
|
auto var = d->scope.lookup(node.getName().getValue());
|
||||||
|
|
||||||
if (!var) {
|
if (!var) {
|
||||||
return reportError({
|
return reportError(node, {
|
||||||
"Attempting assignment to undefined var", node.getName().getValue()
|
"Attempting assignment to undefined variable",
|
||||||
|
node.getName().getValue()
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
GUARDED(node.getValue().emit(this));
|
GUARDED(node.getValue().emit(this));
|
||||||
if (!convertAndStore(d, *var, d->retval)) {
|
if (!convertAndStore(d, *var, d->retval)) {
|
||||||
return reportError({
|
return reportError(node, {
|
||||||
"Invalid assignment to variable", node.getName().getValue()
|
"Invalid assignment to variable", node.getName().getValue()
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -347,19 +351,19 @@ bool BitcodeEmitter::emit(Print const& node) {
|
||||||
Type printType = MonicelliType(d->retval->getType());
|
Type printType = MonicelliType(d->retval->getType());
|
||||||
|
|
||||||
if (printType == Type::UNKNOWN) {
|
if (printType == Type::UNKNOWN) {
|
||||||
return reportError({"Attempting to print unknown type"});
|
return reportError(node, {"Attempting to print unknown type"});
|
||||||
}
|
}
|
||||||
|
|
||||||
auto toCall = PUT_NAMES.find(printType);
|
auto toCall = PUT_NAMES.find(printType);
|
||||||
|
|
||||||
if (toCall == PUT_NAMES.end()) {
|
if (toCall == PUT_NAMES.end()) {
|
||||||
return reportError({"Unknown print function for type"});
|
return reportError(node, {"Unknown print function for type"});
|
||||||
}
|
}
|
||||||
|
|
||||||
llvm::Function *callee = module->getFunction(toCall->second);
|
llvm::Function *callee = module->getFunction(toCall->second);
|
||||||
|
|
||||||
if (callee == nullptr) {
|
if (callee == nullptr) {
|
||||||
return reportError({"Print function was not registered"});
|
return reportError(node, {"Print function was not registered"});
|
||||||
}
|
}
|
||||||
|
|
||||||
d->builder.CreateCall(callee, callargs);
|
d->builder.CreateCall(callee, callargs);
|
||||||
|
@ -371,20 +375,23 @@ bool BitcodeEmitter::emit(Input const& node) {
|
||||||
auto lookupResult = d->scope.lookup(node.getVariable().getValue());
|
auto lookupResult = d->scope.lookup(node.getVariable().getValue());
|
||||||
|
|
||||||
if (!lookupResult) {
|
if (!lookupResult) {
|
||||||
return reportError({"Attempting to read undefined variable"});
|
return reportError(node, {
|
||||||
|
"Attempting to read undefined variable",
|
||||||
|
node.getVariable().getValue()
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
llvm::AllocaInst *variable = *lookupResult;
|
llvm::AllocaInst *variable = *lookupResult;
|
||||||
Type inputType = MonicelliType(variable->getAllocatedType());
|
Type inputType = MonicelliType(variable->getAllocatedType());
|
||||||
|
|
||||||
if (inputType == Type::UNKNOWN) {
|
if (inputType == Type::UNKNOWN) {
|
||||||
return reportError({"Attempting to read unknown type"});
|
return reportError(node, {"Attempting to read unknown type"});
|
||||||
}
|
}
|
||||||
|
|
||||||
auto toCall = GET_NAMES.find(inputType);
|
auto toCall = GET_NAMES.find(inputType);
|
||||||
|
|
||||||
if (toCall == GET_NAMES.end()) {
|
if (toCall == GET_NAMES.end()) {
|
||||||
return reportError({
|
return reportError(node, {
|
||||||
"Unknown input function for type"
|
"Unknown input function for type"
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -392,7 +399,7 @@ bool BitcodeEmitter::emit(Input const& node) {
|
||||||
llvm::Function *callee = module->getFunction(toCall->second);
|
llvm::Function *callee = module->getFunction(toCall->second);
|
||||||
|
|
||||||
if (callee == nullptr) {
|
if (callee == nullptr) {
|
||||||
return reportError({
|
return reportError(node, {
|
||||||
"Input function was not registered for type"
|
"Input function was not registered for type"
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -403,11 +410,11 @@ bool BitcodeEmitter::emit(Input const& node) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BitcodeEmitter::emit(Abort const&) {
|
bool BitcodeEmitter::emit(Abort const& node) {
|
||||||
llvm::Function *callee = module->getFunction(ABORT_NAME);
|
llvm::Function *callee = module->getFunction(ABORT_NAME);
|
||||||
|
|
||||||
if (callee == nullptr) {
|
if (callee == nullptr) {
|
||||||
return reportError({"Abort function was not registered"});
|
return reportError(node, {"Abort function was not registered"});
|
||||||
}
|
}
|
||||||
|
|
||||||
d->builder.CreateCall(callee);
|
d->builder.CreateCall(callee);
|
||||||
|
@ -419,7 +426,7 @@ bool BitcodeEmitter::emit(Assert const& node) {
|
||||||
llvm::Function *callee = module->getFunction(ASSERT_NAME);
|
llvm::Function *callee = module->getFunction(ASSERT_NAME);
|
||||||
|
|
||||||
if (callee == nullptr) {
|
if (callee == nullptr) {
|
||||||
return reportError({"Assert function was not registered"});
|
return reportError(node, {"Assert function was not registered"});
|
||||||
}
|
}
|
||||||
|
|
||||||
node.getExpression().emit(this);
|
node.getExpression().emit(this);
|
||||||
|
@ -432,14 +439,14 @@ bool BitcodeEmitter::emit(FunctionCall const& node) {
|
||||||
llvm::Function *callee = module->getFunction(node.getName().getValue());
|
llvm::Function *callee = module->getFunction(node.getName().getValue());
|
||||||
|
|
||||||
if (callee == 0) {
|
if (callee == 0) {
|
||||||
return reportError({
|
return reportError(node, {
|
||||||
"Attempting to call undefined function",
|
"Attempting to call undefined function",
|
||||||
node.getName().getValue() + "()"
|
node.getName().getValue() + "()"
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (callee->arg_size() != node.getArgs().size()) {
|
if (callee->arg_size() != node.getArgs().size()) {
|
||||||
return reportError({
|
return reportError(node, {
|
||||||
"Argument number mismatch in call of",
|
"Argument number mismatch in call of",
|
||||||
node.getName().getValue() + "()",
|
node.getName().getValue() + "()",
|
||||||
"expected", std::to_string(callee->arg_size()),
|
"expected", std::to_string(callee->arg_size()),
|
||||||
|
@ -518,7 +525,7 @@ bool BitcodeEmitter::emit(FunctionPrototype const& node) {
|
||||||
for (FunArg const& arg: node.getArgs()) {
|
for (FunArg const& arg: node.getArgs()) {
|
||||||
std::string const& name = arg.getName().getValue();
|
std::string const& name = arg.getName().getValue();
|
||||||
if (argsSet.find(name) != argsSet.end()) {
|
if (argsSet.find(name) != argsSet.end()) {
|
||||||
return reportError({
|
return reportError(node, {
|
||||||
"Two arguments with same name to function",
|
"Two arguments with same name to function",
|
||||||
node.getName().getValue() + "():", name
|
node.getName().getValue() + "():", name
|
||||||
});
|
});
|
||||||
|
@ -539,13 +546,13 @@ bool BitcodeEmitter::emit(FunctionPrototype const& node) {
|
||||||
func = module->getFunction(node.getName().getValue());
|
func = module->getFunction(node.getName().getValue());
|
||||||
|
|
||||||
if (!func->empty()) {
|
if (!func->empty()) {
|
||||||
return reportError({
|
return reportError(node, {
|
||||||
"Redefining function", node.getName().getValue()
|
"Redefining function", node.getName().getValue()
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (func->arg_size() != node.getArgs().size()) {
|
if (func->arg_size() != node.getArgs().size()) {
|
||||||
return reportError({
|
return reportError(node, {
|
||||||
"Argument number mismatch in definition vs declaration of",
|
"Argument number mismatch in definition vs declaration of",
|
||||||
node.getName().getValue() + "()",
|
node.getName().getValue() + "()",
|
||||||
"expected", std::to_string(func->arg_size()),
|
"expected", std::to_string(func->arg_size()),
|
||||||
|
@ -650,7 +657,7 @@ bool BitcodeEmitter::emit(Id const& node) {
|
||||||
auto value = d->scope.lookup(node.getValue());
|
auto value = d->scope.lookup(node.getValue());
|
||||||
|
|
||||||
if (!value) {
|
if (!value) {
|
||||||
return reportError({
|
return reportError(node, {
|
||||||
"Undefined variable", node.getValue()
|
"Undefined variable", node.getValue()
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -685,17 +692,17 @@ bool BitcodeEmitter::emit(Float const& node) {
|
||||||
|
|
||||||
#define HANDLE_INT_ONLY(op, symbol) \
|
#define HANDLE_INT_ONLY(op, symbol) \
|
||||||
if (fp) { \
|
if (fp) { \
|
||||||
return reportError({"Operator " #symbol " cannot be applied to float values!"}); \
|
return reportError(node, {"Operator " #symbol " cannot be applied to float values!"}); \
|
||||||
} else { \
|
} else { \
|
||||||
d->retval = d->builder.Create##op(left, right); \
|
d->retval = d->builder.Create##op(left, right); \
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
bool createOp(BitcodeEmitter::Private *d, llvm::Value *left, Operator op, llvm::Value *right) {
|
bool createOp(BitcodeEmitter::Private *d, Localizable const& node, llvm::Value *left, Operator op, llvm::Value *right) {
|
||||||
llvm::Type *retType = deduceResultType(left, right);
|
llvm::Type *retType = deduceResultType(left, right);
|
||||||
|
|
||||||
if (retType == nullptr) {
|
if (retType == nullptr) {
|
||||||
return reportError({"Cannot combine operators."});
|
return reportError(node, {"Cannot combine operators."});
|
||||||
}
|
}
|
||||||
|
|
||||||
bool fp = isFP(retType);
|
bool fp = isFP(retType);
|
||||||
|
@ -704,7 +711,7 @@ bool createOp(BitcodeEmitter::Private *d, llvm::Value *left, Operator op, llvm::
|
||||||
right = coerce(d, right, retType);
|
right = coerce(d, right, retType);
|
||||||
|
|
||||||
if (left == nullptr || right == nullptr) {
|
if (left == nullptr || right == nullptr) {
|
||||||
return reportError({"Cannot convert operators to result type."});
|
return reportError(node, {"Cannot convert operators to result type."});
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (op) {
|
switch (op) {
|
||||||
|
@ -756,7 +763,7 @@ bool BitcodeEmitter::emit(BinaryExpression const& expression) {
|
||||||
GUARDED(expression.getRight().emit(this));
|
GUARDED(expression.getRight().emit(this));
|
||||||
llvm::Value *right = d->retval;
|
llvm::Value *right = d->retval;
|
||||||
|
|
||||||
GUARDED(createOp(d, left, expression.getOperator(), right));
|
GUARDED(createOp(d, expression, left, expression.getOperator(), right));
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -768,7 +775,7 @@ bool BitcodeEmitter::emitSemiExpression(Id const& left, SemiExpression const& ri
|
||||||
GUARDED(right.getLeft().emit(this));
|
GUARDED(right.getLeft().emit(this));
|
||||||
llvm::Value *rhs = d->retval;
|
llvm::Value *rhs = d->retval;
|
||||||
|
|
||||||
GUARDED(createOp(d, lhs, right.getOperator(), rhs));
|
GUARDED(createOp(d, right, lhs, right.getOperator(), rhs));
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -126,9 +126,10 @@
|
||||||
%type<assignval> assign_stmt
|
%type<assignval> assign_stmt
|
||||||
%type<loopval> loop_stmt
|
%type<loopval> loop_stmt
|
||||||
%type<returnval> return_stmt
|
%type<returnval> return_stmt
|
||||||
%type<expressionval> expression maybe_expression simple_expression var_init
|
%type<expressionval> expression maybe_expression simple_expression expression_inner
|
||||||
|
%type<expressionval> var_init
|
||||||
%type<exprlistval> call_arglist call_args
|
%type<exprlistval> call_arglist call_args
|
||||||
%type<semiexpval> semi_expression
|
%type<semiexpval> semi_expression semi_expression_inner
|
||||||
%type<idval> variable
|
%type<idval> variable
|
||||||
%type<numericval> numeric
|
%type<numericval> numeric
|
||||||
%type<boolval> pointer
|
%type<boolval> pointer
|
||||||
|
@ -196,6 +197,7 @@ statements:
|
||||||
}
|
}
|
||||||
| statements statement {
|
| statements statement {
|
||||||
if ($2 != nullptr) {
|
if ($2 != nullptr) {
|
||||||
|
$2->setLocation(@2);
|
||||||
$1->push_back($2);
|
$1->push_back($2);
|
||||||
}
|
}
|
||||||
$$ = $1;
|
$$ = $1;
|
||||||
|
@ -268,6 +270,7 @@ loop_stmt:
|
||||||
;
|
;
|
||||||
branch_stmt:
|
branch_stmt:
|
||||||
BRANCH_CONDITION variable BRANCH_BEGIN branch_body BRANCH_END {
|
BRANCH_CONDITION variable BRANCH_BEGIN branch_body BRANCH_END {
|
||||||
|
$2->setLocation(@2);
|
||||||
$$ = new Branch($2, $4);
|
$$ = new Branch($2, $4);
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
@ -329,6 +332,12 @@ assert_stmt:
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
expression:
|
expression:
|
||||||
|
expression_inner {
|
||||||
|
$1->setLocation(@1);
|
||||||
|
$$ = $1;
|
||||||
|
}
|
||||||
|
;
|
||||||
|
expression_inner:
|
||||||
simple_expression {
|
simple_expression {
|
||||||
$$ = $1;
|
$$ = $1;
|
||||||
}
|
}
|
||||||
|
@ -364,6 +373,12 @@ expression:
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
semi_expression:
|
semi_expression:
|
||||||
|
semi_expression_inner {
|
||||||
|
$1->setLocation(@1);
|
||||||
|
$$ = $1;
|
||||||
|
}
|
||||||
|
;
|
||||||
|
semi_expression_inner:
|
||||||
expression {
|
expression {
|
||||||
$$ = new SemiExpEq($1);
|
$$ = new SemiExpEq($1);
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,8 @@
|
||||||
#include "Emitter.hpp"
|
#include "Emitter.hpp"
|
||||||
#include "Pointers.hpp"
|
#include "Pointers.hpp"
|
||||||
|
|
||||||
|
#include "location.hh"
|
||||||
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
#include <boost/optional.hpp>
|
#include <boost/optional.hpp>
|
||||||
|
@ -52,20 +54,34 @@ enum class Operator {
|
||||||
|
|
||||||
std::ostream& operator<<(std::ostream&, Operator const&);
|
std::ostream& operator<<(std::ostream&, Operator const&);
|
||||||
|
|
||||||
class Emittable {
|
class Localizable {
|
||||||
|
public:
|
||||||
|
void setLocation(location const& l) {
|
||||||
|
loc = l;
|
||||||
|
}
|
||||||
|
|
||||||
|
location const& getLocation() const {
|
||||||
|
return loc;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
location loc;
|
||||||
|
};
|
||||||
|
|
||||||
|
class Emittable: public Localizable {
|
||||||
public:
|
public:
|
||||||
virtual ~Emittable() {}
|
virtual ~Emittable() {}
|
||||||
virtual bool emit(Emitter *emitter) const = 0;
|
virtual bool emit(Emitter *emitter) const = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class Statement: public Emittable {};
|
class Statement: virtual public Emittable {};
|
||||||
|
|
||||||
class Expression: public Emittable {};
|
class Expression: virtual public Emittable {};
|
||||||
|
|
||||||
class SimpleExpression: public Expression {};
|
class SimpleExpression: public Expression {};
|
||||||
|
|
||||||
class SemiExpression {
|
class SemiExpression: public Localizable {
|
||||||
public:
|
public:
|
||||||
SemiExpression(Operator op, Expression *l): op(op), left(l) {}
|
SemiExpression(Operator op, Expression *l): op(op), left(l) {}
|
||||||
|
|
||||||
|
@ -321,7 +337,7 @@ private:
|
||||||
Pointer<PointerList<Expression>> args;
|
Pointer<PointerList<Expression>> args;
|
||||||
};
|
};
|
||||||
|
|
||||||
class BranchCase {
|
class BranchCase: public Localizable {
|
||||||
public:
|
public:
|
||||||
BranchCase(SemiExpression *c, PointerList<Statement> *b): condition(c), body(b) {}
|
BranchCase(SemiExpression *c, PointerList<Statement> *b): condition(c), body(b) {}
|
||||||
|
|
||||||
|
@ -341,7 +357,7 @@ private:
|
||||||
|
|
||||||
class Branch: public Statement {
|
class Branch: public Statement {
|
||||||
public:
|
public:
|
||||||
class Body {
|
class Body: public Localizable {
|
||||||
public:
|
public:
|
||||||
Body(PointerList<BranchCase> *c, PointerList<Statement> *e = nullptr): cases(c), els(e) {}
|
Body(PointerList<BranchCase> *c, PointerList<Statement> *e = nullptr): cases(c), els(e) {}
|
||||||
|
|
||||||
|
@ -380,7 +396,7 @@ private:
|
||||||
|
|
||||||
Function *makeMain(PointerList<Statement> *body);
|
Function *makeMain(PointerList<Statement> *body);
|
||||||
|
|
||||||
class FunArg {
|
class FunArg: public Localizable {
|
||||||
public:
|
public:
|
||||||
FunArg(Id *n, Type t, bool p): name(n), type(t), pointer(p) {}
|
FunArg(Id *n, Type t, bool p): name(n), type(t), pointer(p) {}
|
||||||
|
|
||||||
|
|
Reference in New Issue
Block a user