#include "AstVisitor.h" #include "Ast.h" #include "ErrorReporting.h" #include #include "Util.h" using namespace qlow; std::unique_ptr StructureVisitor::visit(ast::Class& ast, sem::Scope& scope) { //auto c = std::make_unique(); //c->name = ast.name; //return c; throw "shouldn't be called"; } std::unique_ptr StructureVisitor::visit(ast::FeatureDeclaration& ast, sem::Scope& scope) { // not needed, because throw "shouldn't be called"; } std::unique_ptr StructureVisitor::visit(ast::FieldDeclaration& ast, sem::Scope& scope) { auto f = std::make_unique(scope.getContext()); f->name = ast.name; auto type = scope.getType(ast.type.get()); if (type != sem::NO_TYPE) { f->type = type; } else { throw SemanticError(SemanticError::UNKNOWN_TYPE, ast.type->asString(), ast.type->pos ); } return f; } std::unique_ptr StructureVisitor::visit(ast::MethodDefinition& ast, sem::Scope& scope) { auto returnType = scope.getType(ast.type.get()); if (returnType == sem::NO_TYPE) { throw SemanticError(SemanticError::UNKNOWN_TYPE, ast.type->asString(), ast.type->pos ); } auto m = std::make_unique(scope, returnType); m->name = ast.name; m->astNode = * for (auto& arg : ast.arguments) { auto var = arg->accept(*this, scope); if (dynamic_cast(var.get())) { std::unique_ptr variable = unique_dynamic_cast(std::move(var)); variable->isParameter = true; m->arguments.push_back(variable.get()); std::string varname = variable->name; m->scope.putVariable(varname, std::move(variable)); } else { throw "internal error creating argument"; } } return m; //throw " std::unique_ptr StructureVisitor::visit(ast::MethodDefinition& ast, sem::Scope& scope) shouldn't be called"; } std::unique_ptr StructureVisitor::visit(ast::VariableDeclaration& ast, sem::Scope& scope) { auto v = std::make_unique(scope.getContext()); v->name = ast.name; auto type = scope.getType(ast.type.get()); if (type != sem::NO_TYPE) { v->type = type; } else { throw SemanticError(SemanticError::UNKNOWN_TYPE, ast.type->asString(), ast.type->pos ); } return v; } std::unique_ptr StructureVisitor::visit(ast::Statement& ast, sem::Scope& scope) { printf("at: %d:%d to %d:%d\n", ast.pos.first_line, ast.pos.first_column, ast.pos.last_line, ast.pos.last_column); printf("type: %s\n", typeid(ast).name()); throw "visit(Statement) shouldn't be called"; } std::unique_ptr StructureVisitor::visit(ast::DoEndBlock& ast, sem::Scope& scope) { sem::LocalScope* lscope = dynamic_cast(&scope); if (!lscope) throw "error: non-method scope inside method"; auto body = std::make_unique(*lscope); for (auto& statement : ast.statements) { if (ast::LocalVariableStatement* nvs = dynamic_cast(statement.get()); nvs) { auto type = body->scope.getType(nvs->type.get()); if (type == sem::NO_TYPE) throw SemanticError(SemanticError::UNKNOWN_TYPE, nvs->type->asString(), nvs->type->pos); auto var = std::make_unique(scope.getContext(), std::move(type), nvs->name); body->scope.putVariable(nvs->name, std::move(var)); continue; } auto v = statement->accept(*this, body->scope); if (dynamic_cast(v.get()) != nullptr) { body->statements.push_back( std::make_unique( unique_dynamic_cast(std::move(v)))); } else { body->statements.push_back(unique_dynamic_cast(std::move(v))); } } return body; } std::unique_ptr StructureVisitor::visit(ast::IfElseBlock& ast, sem::Scope& scope) { auto condition = ast.condition->accept(*this, scope); auto ifB = ast.ifBlock->accept(*this, scope); auto eB= ast.elseBlock->accept(*this, scope); if (!dynamic_cast(ifB.get()) || !dynamic_cast(eB.get()) || !dynamic_cast(condition.get())) throw "internal error, invalid if block"; auto condExpr = unique_dynamic_cast(std::move(condition)); auto ifBBlock = unique_dynamic_cast(std::move(ifB)); auto eBBlock= unique_dynamic_cast(std::move(eB)); auto ieb = std::make_unique(std::move(condExpr), std::move(ifBBlock), std::move(eBBlock)); return ieb; } std::unique_ptr StructureVisitor::visit(ast::WhileBlock& ast, sem::Scope& scope) { auto condition = ast.condition->accept(*this, scope); auto body = ast.body->accept(*this, scope); if (!dynamic_cast(body.get()) || !dynamic_cast(condition.get())) throw "internal error, invalid while block"; auto condExpr = unique_dynamic_cast(std::move(condition)); auto bodyblock = unique_dynamic_cast(std::move(body)); auto wb = std::make_unique(std::move(condExpr), std::move(bodyblock)); return wb; } std::unique_ptr StructureVisitor::visit(ast::Expression& ast, sem::Scope& scope) { throw "visit(Expression) shouldn't be called"; } std::unique_ptr StructureVisitor::visit(ast::FeatureCall& ast, sem::Scope& scope) { std::unique_ptr target = nullptr; if (ast.target) { target = unique_dynamic_cast( ast.target->accept(*this, scope)); } sem::Method* method; sem::Variable* var; // TODO rewrite types if (target) { //method = target->type->getScope().getMethod(ast.name); //var = target->type->getScope().getVariable(ast.name); } else { method = scope.getMethod(ast.name); var = scope.getVariable(ast.name); } if (target) { if (var) { return std::make_unique(std::move(target), dynamic_cast(var)); } else if (method) { auto fce = std::make_unique( std::move(target), method); if (ast.arguments.size() != method->arguments.size()) throw SemanticError(SemanticError::WRONG_NUMBER_OF_ARGUMENTS, ast.name, ast.pos); for (size_t i = 0; i < ast.arguments.size(); i++) { auto& arg = ast.arguments[i]; auto& argTypeShouldHave = method->arguments[i]->type; auto argument = arg->accept(*this, scope); if (sem::Expression* expr = dynamic_cast(argument.get()); expr) { if (expr->type != argTypeShouldHave) throw SemanticError(SemanticError::TYPE_MISMATCH, "argument passed to function has wrong type", // TODO rewrite types //expr->type->asString() + "' instead of '" + //argTypeShouldHave->asString() + "'", arg->pos ); fce->arguments.push_back( unique_dynamic_cast(std::move(argument))); } else { throw "internal error: non-expression passed as function parameter"; } } return fce; } else { throw SemanticError(SemanticError::FEATURE_NOT_FOUND, ast.name, ast.pos); } } else if (var) { if (sem::Field* field = dynamic_cast(var); field) { auto* thisExpr = scope.getVariable("this"); if (!thisExpr) throw "no this found"; //Printer::getInstance().debug() << "feature call " << var->toString() << " is a field\n"; return std::make_unique(std::make_unique(thisExpr), field); } else { //Printer::getInstance().debug() << "feature call " << var->toString() << " is not a field\n"; return std::make_unique(var); } } else if (method) { auto fce = std::make_unique(nullptr, method); for (auto& arg : ast.arguments) { auto argument = arg->accept(*this, scope); if (dynamic_cast(argument.get())) { fce->arguments.push_back(unique_dynamic_cast(std::move(argument))); } else { throw "internal error: non-expression passed as function parameter"; } } fce->callee = method; return fce; } else { #ifdef DEBUGGING printf("var not found: %s\n", ast.name.c_str()); printf("current scope: %s\n", scope.toString().c_str()); #endif throw SemanticError(SemanticError::FEATURE_NOT_FOUND, ast.name, ast.pos); } } std::unique_ptr StructureVisitor::visit(ast::AssignmentStatement& ast, sem::Scope& scope) { auto as = std::make_unique(scope.getContext()); // as->value = unique_dynamic_cast(visit(*ast.expr, classes)); // as->target = unique_dynamic_cast(visit(*ast.target, classes)); as->value = unique_dynamic_cast(ast.expr->accept(*this, scope)); as->target = unique_dynamic_cast(ast.target->accept(*this, scope)); if (as->target->type == as->value->type) { return as; } else { throw SemanticError( SemanticError::TYPE_MISMATCH, "Can't assign expression of type to type.", // TODO rewrite //"Can't assign expression of type '" + as->value->type->asString() + //"' to value of type '" + as->target->type->asString() + "'.", ast.pos ); } } std::unique_ptr StructureVisitor::visit(ast::ReturnStatement& ast, sem::Scope& scope) { auto shouldReturn = scope.getReturnableType(); if (shouldReturn == sem::NO_TYPE) { if (ast.expr == nullptr) return std::make_unique(scope.getContext()); else throw SemanticError( SemanticError::INVALID_RETURN_TYPE, "This method should not return any value.", ast.expr->pos ); } else if (ast.expr == nullptr) { throw SemanticError( SemanticError::INVALID_RETURN_TYPE, "This method should return a value.", ast.pos ); } auto returnValue = unique_dynamic_cast(ast.expr->accept(*this, scope)); if (shouldReturn != returnValue->type) { auto should = scope.getContext().getTypeString(shouldReturn); auto is = scope.getContext().getTypeString(returnValue->type); throw SemanticError::invalidReturnType(should, is, ast.expr->pos); } auto as = std::make_unique(scope.getContext()); as->value = std::move(returnValue); return as; } std::unique_ptr StructureVisitor::visit(ast::LocalVariableStatement& ast, sem::Scope& scope) { throw "shouldn't be called"; } std::unique_ptr StructureVisitor::visit( ast::AddressExpression& ast, sem::Scope& scope) { auto target = unique_dynamic_cast(ast.target->accept(*this, scope)); auto targetType = target->type; if (!target->isLValue()) { throw NotLValue(scope.getContext().getTypeString(targetType), ast.pos); } return std::make_unique(std::move(target)); } std::unique_ptr StructureVisitor::visit(ast::IntConst& ast, sem::Scope& scope) { return std::make_unique(scope.getContext(), ast.value); } std::unique_ptr StructureVisitor::visit(ast::UnaryOperation& ast, sem::Scope& scope) { auto argument = unique_dynamic_cast(ast.expr->accept(*this, scope)); auto ret = std::make_unique(scope.getContext(), argument->type); // TODO not a feasible assumption ret->opString = ast.opString; ret->side = ast.side; ret->arg = std::move(argument); return ret; } std::unique_ptr StructureVisitor::visit(ast::BinaryOperation& ast, sem::Scope& scope) { auto leftEval = unique_dynamic_cast(ast.left->accept(*this, scope)); auto rightEval = unique_dynamic_cast(ast.right->accept(*this, scope)); throw SemanticError(SemanticError::OPERATOR_NOT_FOUND, "TODO implement", ast.pos); /* sem::Method* operationMethod = leftEval->type->getScope().resolveMethod( ast.opString, { rightEval->type } ); Printer::getInstance().debug() << "looked for operation method for operator " << ast.opString << std::endl; if (!operationMethod) { throw SemanticError(SemanticError::OPERATOR_NOT_FOUND, "operator " + ast.opString + " not found for types '" + leftEval->type->asString() + "' and '" + rightEval->type->asString() + "'", ast.opPos); } auto ret = std::make_unique(leftEval->type, &ast); ret->operationMethod = operationMethod; ret->opString = ast.opString; ret->left = std::move(leftEval); ret->right = std::move(rightEval); return ret;*/ } std::unique_ptr StructureVisitor::visit(ast::NewArrayExpression& ast, sem::Scope& scope) { auto ret = std::make_unique(scope.getContext(), scope.getType(ast.type.get())); return ret; } std::unique_ptr StructureVisitor::visit(ast::CastExpression& ast, sem::Scope& scope) { auto expr = unique_dynamic_cast(ast.expression->accept(*this, scope)); auto type = scope.getType(ast.targetType.get()); return std::make_unique( std::move(expr), type, &ast); }