add boolean variables/arguments/return values (w/o type checking)
This commit is contained in:
parent
9d14c30d81
commit
c7a4effaab
|
@ -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 {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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 {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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';
|
||||||
|
|
Loading…
Reference in a new issue