diff --git a/bootstrap/emit.cc b/bootstrap/emit.cc index 74cb7c9..d4d37cb 100644 --- a/bootstrap/emit.cc +++ b/bootstrap/emit.cc @@ -34,13 +34,6 @@ std::any EmitVisitor::visitFunction(xlangParser::FunctionContext *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()) { int block = blockcount++; @@ -78,10 +71,12 @@ std::any EmitVisitor::visitStatement(xlangParser::StatementContext *ctx) { if (ctx->Break()) { output << " jmp @while" << loopstack.back() << "_end" << std::endl; output << "@dead" << blockcount++ << std::endl; + return {}; } if (ctx->Continue()) { output << " jmp @while" << loopstack.back() << "_expr" << std::endl; output << "@dead" << blockcount++ << std::endl; + return {}; } if (ctx->Return()) { tmpcount = 0; @@ -97,7 +92,7 @@ std::any EmitVisitor::visitStatement(xlangParser::StatementContext *ctx) { << std::endl; return {}; } - // unreachable + visitValue(ctx->value()); return {}; } @@ -189,6 +184,12 @@ std::any EmitVisitor::visitFactor(xlangParser::FactorContext *ctx) { std::any EmitVisitor::visitVariable(xlangParser::VariableContext *ctx) { 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()) { std::vector args; @@ -203,9 +204,9 @@ std::any EmitVisitor::visitVariable(xlangParser::VariableContext *ctx) { output << "w " << arg << ", "; } output << ")" << std::endl; - } else { - last = "%_" + name; + return {}; } + last = "%_" + name; return {}; } diff --git a/bootstrap/typecheck.cc b/bootstrap/typecheck.cc index e0fb063..8afb90a 100644 --- a/bootstrap/typecheck.cc +++ b/bootstrap/typecheck.cc @@ -9,8 +9,10 @@ std::string typeToString(Type type) { return "int"; case Type::Boolean: return "bool"; + default: + case Type::Invalid: + return ""; } - return ""; } TypeCheckVisitor::TypeCheckVisitor(ErrorListener &errorlistener) @@ -73,30 +75,6 @@ std::any TypeCheckVisitor::visitBlock(xlangParser::BlockContext *ctx) { } std::any TypeCheckVisitor::visitStatement(xlangParser::StatementContext *ctx) { - if (auto identifier = ctx->Identifier()) { - auto name = identifier->getSymbol()->getText(); - auto type = std::any_cast(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()) { auto type = std::any_cast(visitCondition(condition)); @@ -230,12 +208,34 @@ std::any TypeCheckVisitor::visitVariable(xlangParser::VariableContext *ctx) { auto token = ctx->Identifier()->getSymbol(); auto name = token->getText(); + if (ctx->Define()) { + auto type = std::any_cast(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(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()) { auto it = signatures.find(name); if (it == signatures.end()) { errorlistener.unknownFunction(token, name); - return Type::Integer; + return Type::Invalid; } else { auto signature = it->second; auto arity = signature.parametertypes.size(); @@ -262,16 +262,13 @@ std::any TypeCheckVisitor::visitVariable(xlangParser::VariableContext *ctx) { } return signature.returntype; } - } else { - auto type = scope.get(name); - if (!type) { - errorlistener.unknownVariable(token, name); - return Type::Integer; - } - return *type; } - // unreachable - errorlistener.compilerError(__FILE__, __LINE__); + if (auto type = scope.get(name)) { + return *type; + } else { + errorlistener.unknownVariable(token, name); + return Type::Invalid; + } } } // namespace xlang diff --git a/bootstrap/typecheck.hh b/bootstrap/typecheck.hh index 0d318be..9cfca99 100644 --- a/bootstrap/typecheck.hh +++ b/bootstrap/typecheck.hh @@ -12,6 +12,7 @@ class ErrorListener; enum class Type { + Invalid, Integer, Boolean, }; diff --git a/bootstrap/xlang.g4 b/bootstrap/xlang.g4 index 4aa4bee..d1fa872 100644 --- a/bootstrap/xlang.g4 +++ b/bootstrap/xlang.g4 @@ -7,14 +7,13 @@ type : TypeInteger | TypeBoolean ; block : LeftBrace statement* RightBrace; -statement : Identifier Define value Semicolon - | Identifier Assign value Semicolon - | If condition block (Else block)? +statement : If condition block (Else block)? | While condition block | Break Semicolon | Continue Semicolon | Return value Semicolon | Print value Semicolon + | value Semicolon ; value : expr | condition @@ -42,6 +41,8 @@ factor : Minus factor | LeftParen expr RightParen ; variable : Identifier + | Identifier Define value + | Identifier Assign value | Identifier LeftParen argumentList? RightParen ; argumentList : value (Comma value)*;