add boolean variables/arguments/return values (w/o type checking)

development
Thomas Lindner 2023-01-06 18:46:45 +01:00
parent 9d14c30d81
commit c7a4effaab
5 changed files with 84 additions and 74 deletions

View File

@ -20,9 +20,9 @@ std::any EmitVisitor::visitFunction(xlangParser::FunctionContext *ctx) {
output << std::endl
<< "export function w $" << ctx->Identifier()->getSymbol()->getText()
<< "(";
if (auto arg_list = ctx->argumentList()) {
for (const auto arg : arg_list->Identifier()) {
output << "w %_" << arg->getSymbol()->getText() << ", ";
if (auto param_list = ctx->parameterList()) {
for (const auto param : param_list->Identifier()) {
output << "w %_" << param->getSymbol()->getText() << ", ";
}
}
output << ")" << std::endl << "{" << std::endl << "@start" << std::endl;
@ -36,7 +36,7 @@ std::any EmitVisitor::visitFunction(xlangParser::FunctionContext *ctx) {
std::any EmitVisitor::visitStatement(xlangParser::StatementContext *ctx) {
if (auto identifier = ctx->Identifier()) {
tmpcount = 0;
visitExpr(ctx->expr());
visitValue(ctx->value());
output << " %_" << identifier->getSymbol()->getText() << " = w copy "
<< last << std::endl;
return {};
@ -73,14 +73,14 @@ std::any EmitVisitor::visitStatement(xlangParser::StatementContext *ctx) {
}
if (ctx->Return()) {
tmpcount = 0;
visitExpr(ctx->expr());
visitValue(ctx->value());
output << " ret " << last << std::endl;
output << "@dead" << blockcount++ << std::endl;
return {};
}
if (ctx->Print()) {
tmpcount = 0;
visitExpr(ctx->expr());
visitValue(ctx->value());
output << " call $printf(l $printformat, ..., w " << last << ")"
<< std::endl;
return {};
@ -129,7 +129,7 @@ std::any EmitVisitor::visitBoolean(xlangParser::BooleanContext *ctx) {
last = "0";
return {};
}
visitCondition(ctx->condition());
visitChildren(ctx);
return {};
}
@ -169,27 +169,29 @@ std::any EmitVisitor::visitFactor(xlangParser::FactorContext *ctx) {
last = integer->getSymbol()->getText();
return {};
}
if (auto identifier = ctx->Identifier()) {
if (ctx->LeftParen()) {
std::vector<std::string> args;
if (auto expr_list = ctx->exprList()) {
for (auto expr : expr_list->expr()) {
visitExpr(expr);
args.emplace_back(last);
}
visitChildren(ctx);
return {};
}
std::any EmitVisitor::visitVariable(xlangParser::VariableContext *ctx) {
auto name = ctx->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);
args.emplace_back(last);
}
output << " " << tmp() << " = w call $"
<< identifier->getSymbol()->getText() << "(";
for (auto arg : args) {
output << "w " << arg << ", ";
}
output << ")" << std::endl;
} else {
last = "%_" + identifier->getSymbol()->getText();
}
return {};
output << " " << tmp() << " = w call $" << name << "(";
for (auto arg : args) {
output << "w " << arg << ", ";
}
output << ")" << std::endl;
} else {
last = "%_" + name;
}
visitExpr(ctx->expr());
return {};
}

View File

@ -26,6 +26,7 @@ class EmitVisitor : public xlangBaseVisitor {
std::any visitExpr(xlangParser::ExprContext *ctx) override;
std::any visitTerm(xlangParser::TermContext *ctx) override;
std::any visitFactor(xlangParser::FactorContext *ctx) override;
std::any visitVariable(xlangParser::VariableContext *ctx) override;
};
} // namespace xlang

View File

@ -26,8 +26,8 @@ std::any TypeCheckVisitor::visitFile(xlangParser::FileContext *ctx) {
"duplicate function '" + name + "'");
continue;
}
if (auto arg_list = function->argumentList()) {
function_arity[name] = arg_list->Identifier().size();
if (auto param_list = function->parameterList()) {
function_arity[name] = param_list->Identifier().size();
} else {
function_arity[name] = 0;
}
@ -38,9 +38,9 @@ std::any TypeCheckVisitor::visitFile(xlangParser::FileContext *ctx) {
std::any TypeCheckVisitor::visitFunction(xlangParser::FunctionContext *ctx) {
scope.emplace_back();
if (auto arg_list = ctx->argumentList()) {
for (const auto arg : arg_list->Identifier()) {
scope.back().emplace(arg->getSymbol()->getText());
if (auto param_list = ctx->parameterList()) {
for (const auto param : param_list->Identifier()) {
scope.back().emplace(param->getSymbol()->getText());
}
}
visitBlock(ctx->block());
@ -57,7 +57,7 @@ std::any TypeCheckVisitor::visitBlock(xlangParser::BlockContext *ctx) {
std::any TypeCheckVisitor::visitStatement(xlangParser::StatementContext *ctx) {
if (auto identifier = ctx->Identifier()) {
visitExpr(ctx->expr());
visitValue(ctx->value());
scope.back().emplace(identifier->getSymbol()->getText());
return {};
}
@ -65,45 +65,46 @@ std::any TypeCheckVisitor::visitStatement(xlangParser::StatementContext *ctx) {
return {};
}
std::any TypeCheckVisitor::visitFactor(xlangParser::FactorContext *ctx) {
if (auto identifier = ctx->Identifier()) {
auto token = identifier->getSymbol();
auto name = token->getText();
if (ctx->LeftParen()) {
if (function_arity.find(name) != function_arity.end()) {
if (auto expr_list = ctx->exprList()) {
auto arity = function_arity[name];
auto arg_num = expr_list->expr().size();
if (arity != arg_num) {
errorlistener.typeError(
token->getLine(), token->getCharPositionInLine(),
"function '" + name + "' expects " + std::to_string(arity) +
" arguments, but got " + std::to_string(arg_num));
}
} else {
if (auto arity = function_arity[name]) {
errorlistener.typeError(
token->getLine(), token->getCharPositionInLine(),
"function '" + name + "' expects " + std::to_string(arity) +
" arguments, but got none");
}
std::any TypeCheckVisitor::visitVariable(xlangParser::VariableContext *ctx) {
auto token = ctx->Identifier()->getSymbol();
auto name = token->getText();
auto line = token->getLine();
auto charPositionInLine = token->getCharPositionInLine();
if (ctx->LeftParen()) {
auto it = function_arity.find(name);
if (it == function_arity.end()) {
errorlistener.typeError(line, charPositionInLine,
"unknown function '" + name + "'");
} else {
auto arity = it->second;
if (auto arg_list = ctx->argumentList()) {
auto arg_num = arg_list->value().size();
if (arity != arg_num) {
errorlistener.typeError(
line, charPositionInLine,
"function '" + name + "' expects " + std::to_string(arity) +
" arguments, but got " + std::to_string(arg_num));
}
} else {
errorlistener.typeError(token->getLine(),
token->getCharPositionInLine(),
"unknown function '" + name + "'");
}
visitChildren(ctx);
} else {
if (!inScope(name)) {
errorlistener.typeError(token->getLine(),
token->getCharPositionInLine(),
"variable '" + name + "' is not in scope");
if (arity) {
errorlistener.typeError(line, charPositionInLine,
"function '" + name + "' expects " +
std::to_string(arity) +
" arguments, but got none");
}
}
}
return {};
visitChildren(ctx);
} else {
if (!inScope(name)) {
errorlistener.typeError(line, charPositionInLine,
"variable '" + name + "' is not in scope");
}
}
visitChildren(ctx);
return {};
}

View File

@ -23,7 +23,7 @@ class TypeCheckVisitor : public xlangBaseVisitor {
std::any visitFunction(xlangParser::FunctionContext *ctx) override;
std::any visitBlock(xlangParser::BlockContext *ctx) override;
std::any visitStatement(xlangParser::StatementContext *ctx) override;
std::any visitFactor(xlangParser::FactorContext *ctx) override;
std::any visitVariable(xlangParser::VariableContext *ctx) override;
};
} // namespace xlang

View File

@ -1,15 +1,18 @@
grammar xlang;
file : function+ EOF;
function : Identifier LeftParen argumentList? RightParen block;
argumentList : Identifier (Comma Identifier)*;
function : Identifier LeftParen parameterList? RightParen block;
parameterList : Identifier (Comma Identifier)*;
block : LeftBrace statement* RightBrace;
statement : Identifier Assign expr Semicolon
statement : Identifier Assign value Semicolon
| If condition block (Else block)?
| While condition block
| Return expr Semicolon
| Print expr Semicolon
| Return value Semicolon
| Print value Semicolon
;
value : expr
| condition
;
condition : condition (And|Or|Xor) boolean
| boolean
;
@ -17,6 +20,7 @@ boolean : Not boolean
| expr (Less|LessEqual|Greater|GreaterEqual|Equal|NotEqual) expr
| True
| False
| variable
| LeftParen condition RightParen
;
expr : expr (Plus|Minus|BitAnd|BitOr|BitXor|ShiftLeft|ShiftRight) term
@ -28,11 +32,13 @@ term : term (Mul|Div) factor
factor : Minus factor
| BitNot factor
| Integer
| Identifier
| Identifier LeftParen exprList? RightParen
| variable
| LeftParen expr RightParen
;
exprList : expr (Comma expr)*;
variable : Identifier
| Identifier LeftParen argumentList? RightParen
;
argumentList : value (Comma value)*;
If : 'if';
Else : 'else';