avoid recursion and ambiguity

This commit is contained in:
Thomas Lindner 2023-01-13 00:07:00 +01:00
parent 61dbff27b3
commit 3f3f323898
5 changed files with 323 additions and 277 deletions

View file

@ -21,8 +21,8 @@ std::any EmitVisitor::visitFunction(xlangParser::FunctionContext *ctx) {
<< "export function w $" << ctx->Identifier()->getSymbol()->getText()
<< "(";
if (auto param_list = ctx->parameterList()) {
for (const auto param : param_list->Identifier()) {
output << "w %_" << param->getSymbol()->getText() << ", ";
for (auto param : param_list->parameter()) {
output << "w %_" << param->Identifier()->getSymbol()->getText() << ", ";
}
}
output << ")" << std::endl << "{" << std::endl << "@start" << std::endl;
@ -36,10 +36,9 @@ std::any EmitVisitor::visitFunction(xlangParser::FunctionContext *ctx) {
std::any EmitVisitor::visitStatement(xlangParser::StatementContext *ctx) {
if (ctx->If()) {
int block = blockcount++;
output << "@if" << block << "_expr" << std::endl;
tmpcount = 0;
visitCondition(ctx->condition());
visitExpr(ctx->expr(0));
output << " jnz " << last << ", @if" << block << "_then, @if" << block
<< "_else" << std::endl;
output << "@if" << block << "_then" << std::endl;
@ -54,12 +53,11 @@ std::any EmitVisitor::visitStatement(xlangParser::StatementContext *ctx) {
}
if (ctx->While()) {
int block = blockcount++;
loopstack.push_back(block);
output << "@loop" << block << "_continue" << std::endl;
output << "@loop" << block << "_expr" << std::endl;
tmpcount = 0;
visitCondition(ctx->condition());
visitExpr(ctx->expr(0));
output << " jnz " << last << ", @loop" << block << "_body, @loop" << block
<< "_end" << std::endl;
output << "@loop" << block << "_body" << std::endl;
@ -71,20 +69,19 @@ std::any EmitVisitor::visitStatement(xlangParser::StatementContext *ctx) {
}
if (ctx->For()) {
int block = blockcount++;
loopstack.push_back(block);
tmpcount = 0;
visitValue(ctx->value(0));
visitExpr(ctx->expr(0));
output << "@loop" << block << "_expr" << std::endl;
tmpcount = 0;
visitCondition(ctx->condition());
visitExpr(ctx->expr(1));
output << " jnz " << last << ", @loop" << block << "_body, @loop" << block
<< "_end" << std::endl;
output << "@loop" << block << "_body" << std::endl;
visitBlock(ctx->block(0));
output << "@loop" << block << "_continue" << std::endl;
tmpcount = 0;
visitValue(ctx->value(1));
visitExpr(ctx->expr(2));
output << " jmp @loop" << block << "_expr" << std::endl;
output << "@loop" << block << "_end" << std::endl;
loopstack.pop_back();
@ -114,44 +111,74 @@ std::any EmitVisitor::visitStatement(xlangParser::StatementContext *ctx) {
}
if (ctx->Return()) {
tmpcount = 0;
visitValue(ctx->value(0));
visitExpr(ctx->expr(0));
output << " ret " << last << std::endl;
output << "@dead" << blockcount++ << std::endl;
return {};
}
if (ctx->Print()) {
tmpcount = 0;
visitValue(ctx->value(0));
visitExpr(ctx->expr(0));
output << " call $printf(l $printformat, ..., w " << last << ")"
<< std::endl;
return {};
}
visitValue(ctx->value(0));
visitExpr(ctx->expr(0));
return {};
}
#define OPERATOR(Operator, visitLeft, left, visitRight, right, ssa_op) \
if (ctx->Operator()) { \
visitLeft(ctx->left); \
std::string l = last; \
visitRight(ctx->right); \
std::string r = last; \
output << " " << tmp() << " = w " ssa_op " " << l << ", " << r \
std::any EmitVisitor::visitExpr(xlangParser::ExprContext *ctx) {
if (auto op = ctx->assignmentOp()) {
auto name = ctx->Identifier()->getSymbol()->getText();
if (op->Define() || op->Assign()) {
visitExpr(ctx->expr());
output << " %_" << name << " = w copy " << last << std::endl;
last = "%_" + name;
return {};
}
if (op->Increment()) {
visitExpr(ctx->expr());
output << " %_" << name << " = w add %_" << name << ", " << last
<< std::endl;
last = "%_" + name;
return {};
}
if (op->Decrement()) {
visitExpr(ctx->expr());
output << " %_" << name << " = w sub %_" << name << ", " << last
<< std::endl;
last = "%_" + name;
return {};
}
}
visitBooleanExpr(ctx->booleanExpr());
return {};
}
#define OPERATOR(Operator, ssa_op) \
if (op->Operator()) { \
output << " " << tmp() << " = w " ssa_op " " << left << ", " << right \
<< std::endl; \
return {}; \
}
std::any EmitVisitor::visitCondition(xlangParser::ConditionContext *ctx) {
OPERATOR(And, visitCondition, condition(), visitBoolean, boolean(), "and");
OPERATOR(Or, visitCondition, condition(), visitBoolean, boolean(), "or");
OPERATOR(Xor, visitCondition, condition(), visitBoolean, boolean(), "xor");
visitBoolean(ctx->boolean());
std::any EmitVisitor::visitBooleanExpr(xlangParser::BooleanExprContext *ctx) {
visitComparisonExpr(ctx->comparisonExpr(0));
for (size_t i = 0, n = ctx->booleanOp().size(); i < n; i++) {
std::string left = last;
visitComparisonExpr(ctx->comparisonExpr(i + 1));
std::string right = last;
auto op = ctx->booleanOp(i);
OPERATOR(And, "and");
OPERATOR(Or, "or");
OPERATOR(Xor, "xor");
}
return {};
}
std::any EmitVisitor::visitBoolean(xlangParser::BooleanContext *ctx) {
std::any EmitVisitor::visitComparisonExpr(
xlangParser::ComparisonExprContext *ctx) {
if (ctx->Not()) {
visitBoolean(ctx->boolean());
visitComparisonExpr(ctx->comparisonExpr());
std::string b = last;
output << " " << tmp() << " = w xor 1, " << b << std::endl;
return {};
@ -164,33 +191,51 @@ std::any EmitVisitor::visitBoolean(xlangParser::BooleanContext *ctx) {
last = "0";
return {};
}
OPERATOR(Less, visitExpr, expr(0), visitExpr, expr(1), "csltw");
OPERATOR(LessEqual, visitExpr, expr(0), visitExpr, expr(1), "cslew");
OPERATOR(Greater, visitExpr, expr(0), visitExpr, expr(1), "csgtw");
OPERATOR(GreaterEqual, visitExpr, expr(0), visitExpr, expr(1), "csgew");
OPERATOR(Equal, visitExpr, expr(0), visitExpr, expr(1), "ceqw");
OPERATOR(NotEqual, visitExpr, expr(0), visitExpr, expr(1), "cnew");
visitChildren(ctx);
visitAdditiveExpr(ctx->additiveExpr(0));
if (auto op = ctx->comparisonOp()) {
std::string left = last;
visitAdditiveExpr(ctx->additiveExpr(1));
std::string right = last;
OPERATOR(Less, "csltw");
OPERATOR(LessEqual, "cslew");
OPERATOR(Greater, "csgtw");
OPERATOR(GreaterEqual, "csgew");
OPERATOR(Equal, "ceqw");
OPERATOR(NotEqual, "cnew");
}
return {};
}
std::any EmitVisitor::visitExpr(xlangParser::ExprContext *ctx) {
OPERATOR(Plus, visitExpr, expr(), visitTerm, term(), "add");
OPERATOR(Minus, visitExpr, expr(), visitTerm, term(), "sub");
OPERATOR(BitAnd, visitExpr, expr(), visitTerm, term(), "and");
OPERATOR(BitOr, visitExpr, expr(), visitTerm, term(), "or");
OPERATOR(BitXor, visitExpr, expr(), visitTerm, term(), "xor");
OPERATOR(ShiftLeft, visitExpr, expr(), visitTerm, term(), "shl");
OPERATOR(ShiftRight, visitExpr, expr(), visitTerm, term(), "shr");
visitTerm(ctx->term());
std::any EmitVisitor::visitAdditiveExpr(xlangParser::AdditiveExprContext *ctx) {
visitMultiplicativeExpr(ctx->multiplicativeExpr(0));
for (size_t i = 0, n = ctx->additiveOp().size(); i < n; i++) {
std::string left = last;
visitMultiplicativeExpr(ctx->multiplicativeExpr(i + 1));
std::string right = last;
auto op = ctx->additiveOp(i);
OPERATOR(Plus, "add");
OPERATOR(Minus, "sub");
OPERATOR(BitAnd, "and");
OPERATOR(BitOr, "or");
OPERATOR(BitXor, "xor");
OPERATOR(ShiftLeft, "shl");
OPERATOR(ShiftRight, "shr");
}
return {};
}
std::any EmitVisitor::visitTerm(xlangParser::TermContext *ctx) {
OPERATOR(Mul, visitTerm, term(), visitFactor, factor(), "mul");
OPERATOR(Div, visitTerm, term(), visitFactor, factor(), "div");
OPERATOR(Rem, visitTerm, term(), visitFactor, factor(), "rem");
visitFactor(ctx->factor());
std::any EmitVisitor::visitMultiplicativeExpr(
xlangParser::MultiplicativeExprContext *ctx) {
visitFactor(ctx->factor(0));
for (size_t i = 0, n = ctx->multiplicativeOp().size(); i < n; i++) {
std::string left = last;
visitFactor(ctx->factor(i + 1));
std::string right = last;
auto op = ctx->multiplicativeOp(i);
OPERATOR(Mul, "mul");
OPERATOR(Div, "div");
OPERATOR(Rem, "rem");
}
return {};
}
@ -211,39 +256,13 @@ std::any EmitVisitor::visitFactor(xlangParser::FactorContext *ctx) {
last = integer->getSymbol()->getText();
return {};
}
visitChildren(ctx);
return {};
}
std::any EmitVisitor::visitVariable(xlangParser::VariableContext *ctx) {
auto name = ctx->Identifier()->getSymbol()->getText();
if (ctx->Define() || ctx->Assign()) {
visitValue(ctx->value());
output << " %_" << name << " = w copy " << last << std::endl;
last = "%_" + name;
return {};
}
if (ctx->Increment()) {
visitExpr(ctx->expr());
output << " %_" << name << " = w add %_" << name << ", " << last
<< std::endl;
last = "%_" + name;
return {};
}
if (ctx->Decrement()) {
visitExpr(ctx->expr());
output << " %_" << name << " = w sub %_" << name << ", " << last
<< std::endl;
last = "%_" + name;
return {};
}
if (auto identifier = ctx->Identifier()) {
auto name = identifier->getSymbol()->getText();
if (ctx->LeftParen()) {
std::vector<std::string> args;
if (auto arg_list = ctx->argumentList()) {
for (auto value : arg_list->value()) {
visitValue(value);
for (auto expr : arg_list->expr()) {
visitExpr(expr);
args.emplace_back(last);
}
}
@ -253,9 +272,13 @@ std::any EmitVisitor::visitVariable(xlangParser::VariableContext *ctx) {
}
output << ")" << std::endl;
return {};
}
} else {
last = "%_" + name;
return {};
}
}
visitExpr(ctx->expr());
return {};
}
} // namespace xlang

View file

@ -22,12 +22,14 @@ class EmitVisitor : public xlangBaseVisitor {
std::any visitFile(xlangParser::FileContext *ctx) override;
std::any visitFunction(xlangParser::FunctionContext *ctx) override;
std::any visitStatement(xlangParser::StatementContext *ctx) override;
std::any visitCondition(xlangParser::ConditionContext *ctx) override;
std::any visitBoolean(xlangParser::BooleanContext *ctx) override;
std::any visitExpr(xlangParser::ExprContext *ctx) override;
std::any visitTerm(xlangParser::TermContext *ctx) override;
std::any visitBooleanExpr(xlangParser::BooleanExprContext *ctx) override;
std::any visitComparisonExpr(
xlangParser::ComparisonExprContext *ctx) override;
std::any visitAdditiveExpr(xlangParser::AdditiveExprContext *ctx) override;
std::any visitMultiplicativeExpr(
xlangParser::MultiplicativeExprContext *ctx) override;
std::any visitFactor(xlangParser::FactorContext *ctx) override;
std::any visitVariable(xlangParser::VariableContext *ctx) override;
};
} // namespace xlang

View file

@ -22,16 +22,15 @@ std::any TypeCheckVisitor::visitFile(xlangParser::FileContext *ctx) {
for (auto function : ctx->function()) {
auto token = function->Identifier()->getSymbol();
auto name = token->getText();
Signature signature{std::any_cast<Type>(visitType(function->type())), {}};
if (signatures.find(name) != signatures.end()) {
errorlistener.duplicateFunction(token, name);
continue;
}
Signature signature{std::any_cast<Type>(visitType(function->type())), {}};
if (auto param_list = function->parameterList()) {
for (auto type : param_list->type()) {
for (auto param : param_list->parameter()) {
signature.parametertypes.push_back(
std::any_cast<Type>(visitType(type)));
std::any_cast<Type>(visitType(param->type())));
}
}
signatures.emplace(name, signature);
@ -43,10 +42,9 @@ std::any TypeCheckVisitor::visitFile(xlangParser::FileContext *ctx) {
std::any TypeCheckVisitor::visitFunction(xlangParser::FunctionContext *ctx) {
scope.enter();
if (auto param_list = ctx->parameterList()) {
for (size_t i = 0, n = param_list->Identifier().size(); i < n; i++) {
auto name = param_list->Identifier(i)->getSymbol()->getText();
auto type = std::any_cast<Type>(visitType(param_list->type(i)));
for (auto param : param_list->parameter()) {
auto name = param->Identifier()->getSymbol()->getText();
auto type = std::any_cast<Type>(visitType(param->type()));
scope.add(name, type);
}
}
@ -77,10 +75,10 @@ std::any TypeCheckVisitor::visitBlock(xlangParser::BlockContext *ctx) {
std::any TypeCheckVisitor::visitStatement(xlangParser::StatementContext *ctx) {
if (ctx->If()) {
scope.enter();
auto condition = ctx->condition();
auto type = std::any_cast<Type>(visitCondition(condition));
auto expr = ctx->expr(0);
auto type = std::any_cast<Type>(visitExpr(expr));
if (type != Type::Boolean) {
errorlistener.typeMismatch(condition->getStart(), Type::Boolean, type);
errorlistener.typeMismatch(expr->getStart(), Type::Boolean, type);
}
visitBlock(ctx->block(0));
if (ctx->Else()) {
@ -89,19 +87,28 @@ std::any TypeCheckVisitor::visitStatement(xlangParser::StatementContext *ctx) {
scope.leave();
return {};
}
if (ctx->While() || ctx->For()) {
if (ctx->While()) {
scope.enter();
if (ctx->For()) {
visitValue(ctx->value(0));
}
auto condition = ctx->condition();
auto type = std::any_cast<Type>(visitCondition(condition));
auto expr = ctx->expr(0);
auto type = std::any_cast<Type>(visitExpr(expr));
if (type != Type::Boolean) {
errorlistener.typeMismatch(condition->getStart(), Type::Boolean, type);
errorlistener.typeMismatch(expr->getStart(), Type::Boolean, type);
}
loopcount++;
visitBlock(ctx->block(0));
loopcount--;
scope.leave();
return {};
}
if (ctx->For()) {
visitValue(ctx->value(1));
scope.enter();
visitExpr(ctx->expr(0));
auto expr = ctx->expr(1);
auto type = std::any_cast<Type>(visitExpr(expr));
if (type != Type::Boolean) {
errorlistener.typeMismatch(expr->getStart(), Type::Boolean, type);
}
visitExpr(ctx->expr(2));
loopcount++;
visitBlock(ctx->block(0));
loopcount--;
@ -142,120 +149,30 @@ std::any TypeCheckVisitor::visitStatement(xlangParser::StatementContext *ctx) {
return {};
}
if (ctx->Return()) {
auto type = std::any_cast<Type>(visitValue(ctx->value(0)));
auto type = std::any_cast<Type>(visitExpr(ctx->expr(0)));
if (type != returntype) {
errorlistener.typeMismatch(ctx->value(0)->getStart(), returntype, type);
errorlistener.typeMismatch(ctx->expr(0)->getStart(), returntype, type);
}
return {};
}
visitChildren(ctx);
return {};
}
std::any TypeCheckVisitor::visitValue(xlangParser::ValueContext *ctx) {
if (auto expr = ctx->expr()) {
return visitExpr(expr);
}
if (auto condition = ctx->condition()) {
return visitCondition(condition);
}
// unreachable
errorlistener.compilerError(__FILE__, __LINE__);
}
#define CHECKOPERATOR(visitLeft, left, visitRight, right, expected) \
auto lefttype = std::any_cast<Type>(visitLeft(left)); \
auto righttype = std::any_cast<Type>(visitRight(right)); \
\
if (lefttype != expected) { \
errorlistener.typeMismatch(left->getStart(), expected, lefttype); \
} \
if (righttype != expected) { \
errorlistener.typeMismatch(right->getStart(), expected, righttype); \
}
std::any TypeCheckVisitor::visitCondition(xlangParser::ConditionContext *ctx) {
if (auto condition = ctx->condition()) {
CHECKOPERATOR(visitCondition, condition, visitBoolean, ctx->boolean(),
Type::Boolean);
return Type::Boolean;
}
return visitBoolean(ctx->boolean());
}
std::any TypeCheckVisitor::visitBoolean(xlangParser::BooleanContext *ctx) {
if (auto boolean = ctx->boolean()) {
auto type = std::any_cast<Type>(visitBoolean(boolean));
if (type != Type::Boolean) {
errorlistener.typeMismatch(boolean->getStart(), Type::Boolean, type);
}
return Type::Boolean;
}
if (ctx->True() || ctx->False()) {
return Type::Boolean;
}
if (ctx->expr().size()) {
CHECKOPERATOR(visitExpr, ctx->expr(0), visitExpr, ctx->expr(1),
Type::Integer);
return Type::Boolean;
}
if (auto variable = ctx->variable()) {
return visitVariable(variable);
}
return visitCondition(ctx->condition());
}
std::any TypeCheckVisitor::visitExpr(xlangParser::ExprContext *ctx) {
if (auto expr = ctx->expr()) {
CHECKOPERATOR(visitExpr, expr, visitTerm, ctx->term(), Type::Integer);
return Type::Integer;
}
return visitTerm(ctx->term());
}
std::any TypeCheckVisitor::visitTerm(xlangParser::TermContext *ctx) {
if (auto term = ctx->term()) {
CHECKOPERATOR(visitTerm, term, visitFactor, ctx->factor(), Type::Integer);
return Type::Integer;
}
return visitFactor(ctx->factor());
}
std::any TypeCheckVisitor::visitFactor(xlangParser::FactorContext *ctx) {
if (auto factor = ctx->factor()) {
auto type = std::any_cast<Type>(visitFactor(factor));
if (type != Type::Integer) {
errorlistener.typeMismatch(factor->getStart(), Type::Integer, type);
}
return Type::Integer;
}
if (ctx->Integer()) {
return Type::Integer;
}
if (auto variable = ctx->variable()) {
return visitVariable(variable);
}
return visitExpr(ctx->expr());
}
std::any TypeCheckVisitor::visitVariable(xlangParser::VariableContext *ctx) {
if (auto op = ctx->assignmentOp()) {
auto token = ctx->Identifier()->getSymbol();
auto name = token->getText();
if (ctx->Define()) {
auto type = std::any_cast<Type>(visitValue(ctx->value()));
if (op->Define()) {
auto type = std::any_cast<Type>(visitExpr(ctx->expr()));
if (scope.get(name)) {
errorlistener.shadowedVariable(token, name);
}
scope.add(name, type);
return type;
}
if (ctx->Assign()) {
auto type = std::any_cast<Type>(visitValue(ctx->value()));
if (op->Assign()) {
auto type = std::any_cast<Type>(visitExpr(ctx->expr()));
if (auto expected = scope.get(name)) {
if (type != *expected) {
errorlistener.typeMismatch(token, *expected, type);
@ -266,44 +183,149 @@ std::any TypeCheckVisitor::visitVariable(xlangParser::VariableContext *ctx) {
return type;
}
}
if (auto expr = ctx->expr()) {
auto righttype = std::any_cast<Type>(visitExpr(expr));
if (auto lefttype = scope.get(name)) {
if (*lefttype != Type::Integer) {
errorlistener.typeMismatch(token, Type::Integer, *lefttype);
if (op->Increment() || op->Decrement()) {
if (auto type = scope.get(name)) {
if (*type != Type::Integer) {
errorlistener.typeMismatch(token, Type::Integer, *type);
}
} else {
errorlistener.unknownVariable(token, name);
}
if (righttype != Type::Integer) {
errorlistener.typeMismatch(token, Type::Integer, righttype);
auto expr = ctx->expr();
auto type = std::any_cast<Type>(visitExpr(expr));
if (type != Type::Integer) {
errorlistener.typeMismatch(expr->getStart(), Type::Integer, type);
}
return Type::Integer;
}
}
if (auto boolean_expr = ctx->booleanExpr()) {
return visitBooleanExpr(boolean_expr);
}
// unreachable
errorlistener.compilerError(__FILE__, __LINE__);
}
std::any TypeCheckVisitor::visitBooleanExpr(
xlangParser::BooleanExprContext *ctx) {
if (ctx->booleanOp().size()) {
for (auto comparison_expr : ctx->comparisonExpr()) {
auto type = std::any_cast<Type>(visitComparisonExpr(comparison_expr));
if (type != Type::Boolean) {
errorlistener.typeMismatch(comparison_expr->getStart(), Type::Boolean,
type);
}
}
return Type::Boolean;
}
if (auto comparison_expr = ctx->comparisonExpr(0)) {
return visitComparisonExpr(comparison_expr);
}
// unreachable
errorlistener.compilerError(__FILE__, __LINE__);
}
std::any TypeCheckVisitor::visitComparisonExpr(
xlangParser::ComparisonExprContext *ctx) {
if (auto comparison_expr = ctx->comparisonExpr()) {
auto type = std::any_cast<Type>(visitComparisonExpr(comparison_expr));
if (type != Type::Boolean) {
errorlistener.typeMismatch(comparison_expr->getStart(), Type::Boolean,
type);
}
return Type::Boolean;
}
if (ctx->True() || ctx->False()) {
return Type::Boolean;
}
if (ctx->comparisonOp()) {
for (auto additive_expr : ctx->additiveExpr()) {
auto type = std::any_cast<Type>(visitAdditiveExpr(additive_expr));
if (type != Type::Integer) {
errorlistener.typeMismatch(additive_expr->getStart(), Type::Integer,
type);
}
}
return Type::Boolean;
}
if (auto additive_expr = ctx->additiveExpr(0)) {
return visitAdditiveExpr(additive_expr);
}
// unreachable
errorlistener.compilerError(__FILE__, __LINE__);
}
std::any TypeCheckVisitor::visitAdditiveExpr(
xlangParser::AdditiveExprContext *ctx) {
if (ctx->additiveOp().size()) {
for (auto multiplicative_expr : ctx->multiplicativeExpr()) {
auto type =
std::any_cast<Type>(visitMultiplicativeExpr(multiplicative_expr));
if (type != Type::Integer) {
errorlistener.typeMismatch(multiplicative_expr->getStart(),
Type::Integer, type);
}
}
return Type::Integer;
}
if (auto multiplicative_expr = ctx->multiplicativeExpr(0)) {
return visitMultiplicativeExpr(multiplicative_expr);
}
// unreachable
errorlistener.compilerError(__FILE__, __LINE__);
}
std::any TypeCheckVisitor::visitMultiplicativeExpr(
xlangParser::MultiplicativeExprContext *ctx) {
if (ctx->multiplicativeOp().size()) {
for (auto factor : ctx->factor()) {
auto type = std::any_cast<Type>(visitFactor(factor));
if (type != Type::Integer) {
errorlistener.typeMismatch(factor->getStart(), Type::Integer, type);
}
}
return Type::Integer;
}
if (auto factor = ctx->factor(0)) {
return visitFactor(factor);
}
// unreachable
errorlistener.compilerError(__FILE__, __LINE__);
}
std::any TypeCheckVisitor::visitFactor(xlangParser::FactorContext *ctx) {
if (auto factor = ctx->factor()) {
auto type = std::any_cast<Type>(visitFactor(factor));
if (type != Type::Integer) {
errorlistener.typeMismatch(factor->getStart(), Type::Integer, type);
}
return Type::Integer;
}
if (ctx->Integer()) {
return Type::Integer;
}
if (auto identifier = ctx->Identifier()) {
auto token = identifier->getSymbol();
auto name = token->getText();
if (ctx->LeftParen()) {
auto it = signatures.find(name);
if (it == signatures.end()) {
errorlistener.unknownFunction(token, name);
return Type::Invalid;
} else {
auto signature = it->second;
auto arity = signature.parametertypes.size();
if (auto arg_list = ctx->argumentList()) {
auto arg_num = arg_list->value().size();
auto arg_num = arg_list->expr().size();
if (arity != arg_num) {
errorlistener.wrongArgumentNumber(token, name, arity, arg_num);
}
for (size_t i = 0; i < arg_num && i < arity; i++) {
auto type = std::any_cast<Type>(visitValue(arg_list->value(i)));
auto token = arg_list->value(i)->getStart();
auto expr = arg_list->expr(i);
auto type = std::any_cast<Type>(visitExpr(expr));
if (type != signature.parametertypes[i]) {
errorlistener.typeMismatch(token, signature.parametertypes[i],
type);
errorlistener.typeMismatch(expr->getStart(),
signature.parametertypes[i], type);
}
}
} else {
@ -321,5 +343,11 @@ std::any TypeCheckVisitor::visitVariable(xlangParser::VariableContext *ctx) {
return Type::Invalid;
}
}
if (auto expr = ctx->expr()) {
return visitExpr(expr);
}
// unreachable
errorlistener.compilerError(__FILE__, __LINE__);
}
} // namespace xlang

View file

@ -39,13 +39,14 @@ class TypeCheckVisitor : public xlangBaseVisitor {
std::any visitType(xlangParser::TypeContext *ctx) override;
std::any visitBlock(xlangParser::BlockContext *ctx) override;
std::any visitStatement(xlangParser::StatementContext *ctx) override;
std::any visitValue(xlangParser::ValueContext *ctx) override;
std::any visitCondition(xlangParser::ConditionContext *ctx) override;
std::any visitBoolean(xlangParser::BooleanContext *ctx) override;
std::any visitExpr(xlangParser::ExprContext *ctx) override;
std::any visitTerm(xlangParser::TermContext *ctx) override;
std::any visitBooleanExpr(xlangParser::BooleanExprContext *ctx) override;
std::any visitComparisonExpr(
xlangParser::ComparisonExprContext *ctx) override;
std::any visitAdditiveExpr(xlangParser::AdditiveExprContext *ctx) override;
std::any visitMultiplicativeExpr(
xlangParser::MultiplicativeExprContext *ctx) override;
std::any visitFactor(xlangParser::FactorContext *ctx) override;
std::any visitVariable(xlangParser::VariableContext *ctx) override;
};
} // namespace xlang

View file

@ -2,53 +2,45 @@ grammar xlang;
file : function+ EOF;
function : Identifier LeftParen parameterList? RightParen Colon type block;
parameterList : Identifier Colon type (Comma Identifier Colon type)*;
parameterList : parameter (Comma parameter)*;
parameter : Identifier Colon type;
type : TypeInteger
| TypeBoolean
;
block : LeftBrace statement* RightBrace;
statement : If condition block (Else block)?
| While condition block
| For value Semicolon condition Semicolon value block
statement : If expr block (Else block)?
| While expr block
| For expr Semicolon expr Semicolon expr block
| Break Integer? Semicolon
| Continue Integer? Semicolon
| Return value Semicolon
| Print value Semicolon
| value Semicolon
| Return expr Semicolon
| Print expr Semicolon
| expr Semicolon
;
value : expr
| condition
expr : Identifier assignmentOp expr
| booleanExpr
;
condition : condition (And|Or|Xor) boolean
| boolean
;
boolean : Not boolean
assignmentOp : Define | Assign | Increment | Decrement;
booleanExpr : comparisonExpr (booleanOp comparisonExpr)*;
booleanOp : And | Or | Xor;
comparisonExpr : Not comparisonExpr
| True
| False
| expr (Less|LessEqual|Greater|GreaterEqual|Equal|NotEqual) expr
| variable
| LeftParen condition RightParen
;
expr : expr (Plus|Minus|BitAnd|BitOr|BitXor|ShiftLeft|ShiftRight) term
| term
;
term : term (Mul|Div|Rem) factor
| factor
| additiveExpr (comparisonOp additiveExpr)?
;
comparisonOp : Less | LessEqual | Greater | GreaterEqual | Equal | NotEqual;
additiveExpr : multiplicativeExpr (additiveOp multiplicativeExpr)*;
additiveOp : Plus | Minus | BitAnd | BitOr | BitXor | ShiftLeft | ShiftRight;
multiplicativeExpr : factor (multiplicativeOp factor)*;
multiplicativeOp : Mul | Div | Rem;
factor : Minus factor
| BitNot factor
| Integer
| variable
| Identifier
| Identifier LeftParen argumentList? RightParen
| LeftParen expr RightParen
;
variable : Identifier
| Identifier Define value
| Identifier Assign value
| Identifier Increment expr
| Identifier Decrement expr
| Identifier LeftParen argumentList? RightParen
;
argumentList : value (Comma value)*;
argumentList : expr (Comma expr)*;
TypeInteger : 'int';
TypeBoolean : 'bool';