← index
MXVM/src/frontend/ast.cpp
Source: MXVM/src/frontend/ast.cpp
#include "ast.hpp"
#include <sstream>

namespace pascal {

    BlockNode::BlockNode(std::vector<std::unique_ptr<ASTNode>> decls, std::unique_ptr<CompoundStmtNode> stmt)
        : declarations(std::move(decls)), compoundStatement(std::move(stmt)) {}

    ProgramNode::ProgramNode(const std::string &p_name, std::unique_ptr<BlockNode> blk)
        : name(p_name), block(std::move(blk)) {}

    void ASTNode::print(std::ostream &out, int indent) const {
        for (int i = 0; i < indent; ++i)
            out << "  ";
        out << toString() << std::endl;
    }

    void ProgramNode::accept(ASTVisitor &visitor) {
        visitor.visit(*this);
    }

    std::string ProgramNode::toString() const {
        return "Program: " + name;
    }

    void BlockNode::accept(ASTVisitor &visitor) {
        visitor.visit(*this);
    }

    std::string BlockNode::toString() const {
        return "Block with " + std::to_string(declarations.size()) + " declarations";
    }

    void VarDeclNode::accept(ASTVisitor &visitor) {
        visitor.visit(*this);
    }

    std::string VarDeclNode::toString() const {
        std::ostringstream oss;
        oss << "VarDecl: ";
        for (size_t i = 0; i < identifiers.size(); ++i) {
            if (i > 0)
                oss << ", ";
            oss << identifiers[i];
        }
        oss << " : ";
        std::visit([&oss](const auto &t) {
            using T = std::decay_t<decltype(t)>;
            if constexpr (std::is_same_v<T, std::string>) {
                oss << t;
            } else if constexpr (std::is_same_v<T, std::unique_ptr<ASTNode>>) {
                if (t)
                    oss << t->toString();
                else
                    oss << "<null>";
            }
        },
                   type);
        return oss.str();
    }

    void ProcDeclNode::accept(ASTVisitor &visitor) {
        visitor.visit(*this);
    }

    std::string ProcDeclNode::toString() const {
        return "ProcDecl: " + name + " (" + std::to_string(parameters.size()) + " params)";
    }

    void FuncDeclNode::accept(ASTVisitor &visitor) {
        visitor.visit(*this);
    }

    std::string FuncDeclNode::toString() const {
        return "FuncDecl: " + name + " -> " + returnType;
    }

    void ParameterNode::accept(ASTVisitor &visitor) {
        visitor.visit(*this);
    }

    std::string ParameterNode::toString() const {
        std::ostringstream oss;
        oss << "Param: ";
        if (isVar)
            oss << "var ";
        for (size_t i = 0; i < identifiers.size(); ++i) {
            if (i > 0)
                oss << ", ";
            oss << identifiers[i];
        }
        oss << " : " << type;
        return oss.str();
    }

    void CompoundStmtNode::accept(ASTVisitor &visitor) {
        visitor.visit(*this);
    }

    std::string CompoundStmtNode::toString() const {
        return "CompoundStmt: " + std::to_string(statements.size()) + " statements";
    }

    void AssignmentNode::accept(ASTVisitor &visitor) {
        visitor.visit(*this);
    }

    std::string AssignmentNode::toString() const {
        return "Assignment";
    }

    void IfStmtNode::accept(ASTVisitor &visitor) {
        visitor.visit(*this);
    }

    std::string IfStmtNode::toString() const {
        std::string s;
        if (elseStatement != nullptr) {
            s = "with else";
        }
        return "IfStmt " + s;
    }

    void WhileStmtNode::accept(ASTVisitor &visitor) {
        visitor.visit(*this);
    }

    std::string WhileStmtNode::toString() const {
        return "WhileStmt";
    }

    void ForStmtNode::accept(ASTVisitor &visitor) {
        visitor.visit(*this);
    }

    std::string ForStmtNode::toString() const {
        return "ForStmt: " + variable + (isDownto ? " downto" : " to");
    }

    void RepeatStmtNode::accept(ASTVisitor &visitor) {
        visitor.visit(*this);
    }

    void ProcCallNode::accept(ASTVisitor &visitor) {
        visitor.visit(*this);
    }

    std::string ProcCallNode::toString() const {
        return "ProcCall: " + name + " (" + std::to_string(arguments.size()) + " args)";
    }

    void BinaryOpNode::accept(ASTVisitor &visitor) {
        visitor.visit(*this);
    }

    std::string BinaryOpNode::toString() const {
        return "BinaryOp: " + opToString(operator_);
    }

    std::string BinaryOpNode::opToString(OpType op) {
        switch (op) {
        case PLUS:
            return "+";
        case MINUS:
            return "-";
        case MULTIPLY:
            return "*";
        case DIVIDE:
            return "/";
        case DIV:
            return "div";
        case MOD:
            return "mod";
        case EQUAL:
            return "=";
        case NOT_EQUAL:
            return "<>";
        case LESS:
            return "<";
        case LESS_EQUAL:
            return "<=";
        case GREATER:
            return ">";
        case GREATER_EQUAL:
            return ">=";
        case AND:
            return "and";
        case OR:
            return "or";
        default:
            return "unknown";
        }
    }

    void UnaryOpNode::accept(ASTVisitor &visitor) {
        visitor.visit(*this);
    }

    std::string UnaryOpNode::toString() const {
        return "UnaryOp: " + opToString(operator_);
    }

    std::string UnaryOpNode::opToString(Operator op) {
        switch (op) {
        case PLUS:
            return "+";
        case MINUS:
            return "-";
        case NOT:
            return "not";
        default:
            return "unknown";
        }
    }

    void FuncCallNode::accept(ASTVisitor &visitor) {
        visitor.visit(*this);
    }

    std::string FuncCallNode::toString() const {
        return "FuncCall: " + name + " (" + std::to_string(arguments.size()) + " args)";
    }

    void VariableNode::accept(ASTVisitor &visitor) {
        visitor.visit(*this);
    }

    std::string VariableNode::toString() const {
        return "Variable: " + name;
    }

    void NumberNode::accept(ASTVisitor &visitor) {
        visitor.visit(*this);
    }

    std::string NumberNode::toString() const {
        return "Number: " + value + (isInteger ? " (int)" : " (real)");
    }

    void StringNode::accept(ASTVisitor &visitor) {
        visitor.visit(*this);
    }

    std::string StringNode::toString() const {
        return "String: \"" + value + "\"";
    }

    void BooleanNode::accept(ASTVisitor &visitor) {
        visitor.visit(*this);
    }

    std::string BooleanNode::toString() const {
        std::string s;
        if (value) {
            s = "true";
        } else {
            s = "false";
        }
        return "Boolean: " + s;
    }

    void EmptyStmtNode::accept(ASTVisitor &visitor) {
        visitor.visit(*this);
    }

    std::string EmptyStmtNode::toString() const {
        return "EmptyStmt";
    }

    void ConstDeclNode::accept(ASTVisitor &visitor) {
        visitor.visit(*this);
    }

    std::string ConstDeclNode::toString() const {
        return "ConstDecl";
    }

    void CaseStmtNode::accept(ASTVisitor &visitor) {
        visitor.visit(*this);
    }

    std::string CaseStmtNode::toString() const {
        return "CaseStmt: " + std::to_string(branches.size()) + " branches";
    }

    void ArrayTypeNode::accept(ASTVisitor &visitor) {
        visitor.visit(*this);
    }

    std::string ArrayTypeNode::toString() const {
        std::string elemTypeStr = "unknown";
        if (elementType) {
            elemTypeStr = elementType->toString();
        }

        std::string lowerStr = "?";
        if (lowerBound) {
            lowerStr = lowerBound->toString();
        }

        std::string upperStr = "?";
        if (upperBound) {
            upperStr = upperBound->toString();
        }

        return "ArrayType: " + elemTypeStr + "[" + lowerStr + ".." + upperStr + "]";
    }

    std::string ExitNode::toString() const { return "exit"; }

    void ArrayDeclarationNode::accept(ASTVisitor &visitor) {
        visitor.visit(*this);
    }

    std::string ArrayDeclarationNode::toString() const {
        return "ArrayDecl: " + name + " of " + arrayType->toString();
    }

    void ArrayAccessNode::accept(ASTVisitor &visitor) {
        visitor.visit(*this);
    }

    std::string ArrayAccessNode::toString() const {
        return "ArrayAccess: ";
    }

    void ArrayAssignmentNode::accept(ASTVisitor &visitor) {
        visitor.visit(*this);
    }

    std::string ArrayAssignmentNode::toString() const {
        return "ArrayAssignment: " + arrayName + "[" + index->toString() + "] := " + value->toString();
    }

    RecordTypeNode::RecordTypeNode(std::vector<std::unique_ptr<ASTNode>> fields)
        : fields(std::move(fields)) {}

    void RecordTypeNode::accept(ASTVisitor &visitor) { visitor.visit(*this); }

    std::string RecordTypeNode::toString() const { return "RecordType"; }

    RecordDeclarationNode::RecordDeclarationNode(const std::string &name, std::unique_ptr<RecordTypeNode> recordType)
        : name(name), recordType(std::move(recordType)) {}

    void RecordDeclarationNode::accept(ASTVisitor &visitor) { visitor.visit(*this); }

    std::string RecordDeclarationNode::toString() const { return "RecordDeclaration: " + name; }

    FieldAccessNode::FieldAccessNode(std::unique_ptr<ASTNode> recordExpr, const std::string &fieldName)
        : recordExpr(std::move(recordExpr)), fieldName(fieldName) {}

    void FieldAccessNode::accept(ASTVisitor &visitor) { visitor.visit(*this); }

    std::string FieldAccessNode::toString() const { return "FieldAccess: " + fieldName; }

    void TypeDeclNode::accept(ASTVisitor &visitor) {
        visitor.visit(*this);
    }

    void TypeAliasNode::accept(ASTVisitor &visitor) {
        visitor.visit(*this);
    }

    std::string TypeDeclNode::toString() const {
        std::string result = "TypeDeclNode(";
        for (const auto &decl : typeDeclarations) {
            result += decl->toString() + ", ";
        }
        if (!typeDeclarations.empty())
            result.pop_back(), result.pop_back();
        result += ")";
        return result;
    }

    std::string TypeAliasNode::toString() const {
        return "TypeAliasNode(" + typeName + " = " + baseType + ")";
    }

    void ArrayTypeDeclarationNode::accept(ASTVisitor &visitor) {
        visitor.visit(*this);
    }

    std::string ArrayTypeDeclarationNode::toString() const {
        return name;
    }

    void ExitNode::accept(ASTVisitor &visitor) {
        visitor.visit(*this);
    }

    void SimpleTypeNode::accept(ASTVisitor &visitor) {
        visitor.visit(*this);
    }

    void ContinueNode::accept(ASTVisitor &visitor) {
        visitor.visit(*this);
    }

    std::string ContinueNode::toString() const {
        return "Continue Node";
    }

    void BreakNode::accept(ASTVisitor &visitor) {
        visitor.visit(*this);
    }

    std::string BreakNode::toString() const {
        return "Continue Node";
    }

} // namespace pascal