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

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

View file

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

View file

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

View file

@ -23,7 +23,7 @@ class TypeCheckVisitor : public xlangBaseVisitor {
std::any visitFunction(xlangParser::FunctionContext *ctx) override; std::any visitFunction(xlangParser::FunctionContext *ctx) override;
std::any visitBlock(xlangParser::BlockContext *ctx) override; std::any visitBlock(xlangParser::BlockContext *ctx) override;
std::any visitStatement(xlangParser::StatementContext *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 } // namespace xlang

View file

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