make definitions/assignments expressions
This commit is contained in:
parent
514ebfa25a
commit
80643b910c
|
@ -34,13 +34,6 @@ 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()) {
|
|
||||||
tmpcount = 0;
|
|
||||||
visitValue(ctx->value());
|
|
||||||
output << " %_" << identifier->getSymbol()->getText() << " = w copy "
|
|
||||||
<< last << std::endl;
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
if (ctx->If()) {
|
if (ctx->If()) {
|
||||||
int block = blockcount++;
|
int block = blockcount++;
|
||||||
|
|
||||||
|
@ -78,10 +71,12 @@ std::any EmitVisitor::visitStatement(xlangParser::StatementContext *ctx) {
|
||||||
if (ctx->Break()) {
|
if (ctx->Break()) {
|
||||||
output << " jmp @while" << loopstack.back() << "_end" << std::endl;
|
output << " jmp @while" << loopstack.back() << "_end" << std::endl;
|
||||||
output << "@dead" << blockcount++ << std::endl;
|
output << "@dead" << blockcount++ << std::endl;
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
if (ctx->Continue()) {
|
if (ctx->Continue()) {
|
||||||
output << " jmp @while" << loopstack.back() << "_expr" << std::endl;
|
output << " jmp @while" << loopstack.back() << "_expr" << std::endl;
|
||||||
output << "@dead" << blockcount++ << std::endl;
|
output << "@dead" << blockcount++ << std::endl;
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
if (ctx->Return()) {
|
if (ctx->Return()) {
|
||||||
tmpcount = 0;
|
tmpcount = 0;
|
||||||
|
@ -97,7 +92,7 @@ std::any EmitVisitor::visitStatement(xlangParser::StatementContext *ctx) {
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
// unreachable
|
visitValue(ctx->value());
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -189,6 +184,12 @@ std::any EmitVisitor::visitFactor(xlangParser::FactorContext *ctx) {
|
||||||
std::any EmitVisitor::visitVariable(xlangParser::VariableContext *ctx) {
|
std::any EmitVisitor::visitVariable(xlangParser::VariableContext *ctx) {
|
||||||
auto name = ctx->Identifier()->getSymbol()->getText();
|
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->LeftParen()) {
|
if (ctx->LeftParen()) {
|
||||||
std::vector<std::string> args;
|
std::vector<std::string> args;
|
||||||
|
|
||||||
|
@ -203,9 +204,9 @@ std::any EmitVisitor::visitVariable(xlangParser::VariableContext *ctx) {
|
||||||
output << "w " << arg << ", ";
|
output << "w " << arg << ", ";
|
||||||
}
|
}
|
||||||
output << ")" << std::endl;
|
output << ")" << std::endl;
|
||||||
} else {
|
return {};
|
||||||
last = "%_" + name;
|
|
||||||
}
|
}
|
||||||
|
last = "%_" + name;
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,9 +9,11 @@ std::string typeToString(Type type) {
|
||||||
return "int";
|
return "int";
|
||||||
case Type::Boolean:
|
case Type::Boolean:
|
||||||
return "bool";
|
return "bool";
|
||||||
}
|
default:
|
||||||
|
case Type::Invalid:
|
||||||
return "<invalid>";
|
return "<invalid>";
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
TypeCheckVisitor::TypeCheckVisitor(ErrorListener &errorlistener)
|
TypeCheckVisitor::TypeCheckVisitor(ErrorListener &errorlistener)
|
||||||
: errorlistener{errorlistener}, loopcount{0} {}
|
: errorlistener{errorlistener}, loopcount{0} {}
|
||||||
|
@ -73,30 +75,6 @@ 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()) {
|
|
||||||
auto name = identifier->getSymbol()->getText();
|
|
||||||
auto type = std::any_cast<Type>(visitValue(ctx->value()));
|
|
||||||
|
|
||||||
if (ctx->Define()) {
|
|
||||||
if (scope.get(name)) {
|
|
||||||
errorlistener.shadowedVariable(identifier->getSymbol(), name);
|
|
||||||
}
|
|
||||||
scope.add(name, type);
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
if (ctx->Assign()) {
|
|
||||||
if (auto expected = scope.get(name)) {
|
|
||||||
if (type != *expected) {
|
|
||||||
errorlistener.typeMismatch(identifier->getSymbol(), *expected, type);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
errorlistener.unknownVariable(identifier->getSymbol(), name);
|
|
||||||
}
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
// unreachable
|
|
||||||
errorlistener.compilerError(__FILE__, __LINE__);
|
|
||||||
}
|
|
||||||
if (auto condition = ctx->condition()) {
|
if (auto condition = ctx->condition()) {
|
||||||
auto type = std::any_cast<Type>(visitCondition(condition));
|
auto type = std::any_cast<Type>(visitCondition(condition));
|
||||||
|
|
||||||
|
@ -230,12 +208,34 @@ std::any TypeCheckVisitor::visitVariable(xlangParser::VariableContext *ctx) {
|
||||||
auto token = ctx->Identifier()->getSymbol();
|
auto token = ctx->Identifier()->getSymbol();
|
||||||
auto name = token->getText();
|
auto name = token->getText();
|
||||||
|
|
||||||
|
if (ctx->Define()) {
|
||||||
|
auto type = std::any_cast<Type>(visitValue(ctx->value()));
|
||||||
|
|
||||||
|
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 (auto expected = scope.get(name)) {
|
||||||
|
if (type != *expected) {
|
||||||
|
errorlistener.typeMismatch(token, *expected, type);
|
||||||
|
}
|
||||||
|
return *expected;
|
||||||
|
} else {
|
||||||
|
errorlistener.unknownVariable(token, name);
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
}
|
||||||
if (ctx->LeftParen()) {
|
if (ctx->LeftParen()) {
|
||||||
auto it = signatures.find(name);
|
auto it = signatures.find(name);
|
||||||
|
|
||||||
if (it == signatures.end()) {
|
if (it == signatures.end()) {
|
||||||
errorlistener.unknownFunction(token, name);
|
errorlistener.unknownFunction(token, name);
|
||||||
return Type::Integer;
|
return Type::Invalid;
|
||||||
} else {
|
} else {
|
||||||
auto signature = it->second;
|
auto signature = it->second;
|
||||||
auto arity = signature.parametertypes.size();
|
auto arity = signature.parametertypes.size();
|
||||||
|
@ -262,16 +262,13 @@ std::any TypeCheckVisitor::visitVariable(xlangParser::VariableContext *ctx) {
|
||||||
}
|
}
|
||||||
return signature.returntype;
|
return signature.returntype;
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
auto type = scope.get(name);
|
|
||||||
if (!type) {
|
|
||||||
errorlistener.unknownVariable(token, name);
|
|
||||||
return Type::Integer;
|
|
||||||
}
|
}
|
||||||
|
if (auto type = scope.get(name)) {
|
||||||
return *type;
|
return *type;
|
||||||
|
} else {
|
||||||
|
errorlistener.unknownVariable(token, name);
|
||||||
|
return Type::Invalid;
|
||||||
}
|
}
|
||||||
// unreachable
|
|
||||||
errorlistener.compilerError(__FILE__, __LINE__);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace xlang
|
} // namespace xlang
|
||||||
|
|
|
@ -12,6 +12,7 @@ class ErrorListener;
|
||||||
|
|
||||||
enum class Type
|
enum class Type
|
||||||
{
|
{
|
||||||
|
Invalid,
|
||||||
Integer,
|
Integer,
|
||||||
Boolean,
|
Boolean,
|
||||||
};
|
};
|
||||||
|
|
|
@ -7,14 +7,13 @@ type : TypeInteger
|
||||||
| TypeBoolean
|
| TypeBoolean
|
||||||
;
|
;
|
||||||
block : LeftBrace statement* RightBrace;
|
block : LeftBrace statement* RightBrace;
|
||||||
statement : Identifier Define value Semicolon
|
statement : If condition block (Else block)?
|
||||||
| Identifier Assign value Semicolon
|
|
||||||
| If condition block (Else block)?
|
|
||||||
| While condition block
|
| While condition block
|
||||||
| Break Semicolon
|
| Break Semicolon
|
||||||
| Continue Semicolon
|
| Continue Semicolon
|
||||||
| Return value Semicolon
|
| Return value Semicolon
|
||||||
| Print value Semicolon
|
| Print value Semicolon
|
||||||
|
| value Semicolon
|
||||||
;
|
;
|
||||||
value : expr
|
value : expr
|
||||||
| condition
|
| condition
|
||||||
|
@ -42,6 +41,8 @@ factor : Minus factor
|
||||||
| LeftParen expr RightParen
|
| LeftParen expr RightParen
|
||||||
;
|
;
|
||||||
variable : Identifier
|
variable : Identifier
|
||||||
|
| Identifier Define value
|
||||||
|
| Identifier Assign value
|
||||||
| Identifier LeftParen argumentList? RightParen
|
| Identifier LeftParen argumentList? RightParen
|
||||||
;
|
;
|
||||||
argumentList : value (Comma value)*;
|
argumentList : value (Comma value)*;
|
||||||
|
|
Loading…
Reference in a new issue