make definitions/assignments expressions

This commit is contained in:
Thomas Lindner 2023-01-07 15:23:02 +01:00
parent 514ebfa25a
commit 80643b910c
4 changed files with 48 additions and 48 deletions

View file

@ -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 {};
} }

View file

@ -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

View file

@ -12,6 +12,7 @@ class ErrorListener;
enum class Type enum class Type
{ {
Invalid,
Integer, Integer,
Boolean, Boolean,
}; };

View file

@ -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)*;