private String compileMethod(Node node) throws CompilationErrorException {
        StringBuilder builder = new StringBuilder();

        variableMap = new HashMap<>();
        Arrays.fill(localVariables, 0);

        stackDepth = 0;
        maxStackDepth = 0;

        wasReturnInMainBranch = false;

        MethodNode methodNode = (MethodNode) node;

        methodMap.put(methodNode.getName().getValue(), methodNode);

        currentMethod = methodNode;

        String signature;
        // generate method signature
        if (methodNode.getName().getValue().equals("main")) {
            signature = CodeBuilder.METHOD_MAIN_SIGNATURE;
        } else {
            signature = CodeBuilder.methodDeclarationHeader(constructMethodDeclareSignature(methodNode));
        }

        List<Node> variables = methodNode.getVarList().getChildren();

        // declare all variables
        for (Node var : variables) {
            VariableNode variable = (VariableNode) var;
            declareVariable(variable.getVariableName(), typeMap.get(variable.getVariableType()));
        }

        // compile method body
        //builder.append(compileBody(methodNode.getBody()));

        for (Node command : methodNode.getBody().getChildren()) {
            if (command.getNodeType().equals(NodeType.RETURN)) {
                wasReturnInMainBranch = true;
            }
            builder.append(compileCommand(command));
        }

        // write return for void result type
        if (methodNode.getResultType() == ValueNode.ValueType.VOID_VALUE) {
            builder.append("   return\n");
        }

        String body = builder.toString();

        builder.setLength(0);

        // reserve 2 words for temporary variable
        int variablesAmount = 2;
        for (Variable var : variableMap.values()) {
            switch (var.type) {
                case I:
                    variablesAmount += 1;
                    break;

                case D:
                    variablesAmount += 2;
                    break;
            }
        }

        String limits = CodeBuilder.methodLimits(maxStackDepth, variablesAmount);

        String footer = CodeBuilder.METHOD_END;

//        if (!wasReturnInMainBranch && !methodNode.getResultType().equals(ValueNode.ValueType.VOID_VALUE)) {
//            throw new CompilationErrorException(
//                    "Method " + methodNode.getName().getValue() + " must return " + methodNode.getResultType() +" value");
//        }

        builder.append(signature)
                .append(limits)
                .append(body)
                .append(CodeBuilder.returnLabel(currentMethod.getName().getValue())).append(":\n")
                .append(CodeBuilder.returnOperation(typeMap.get(currentMethod.getResultType())))
                .append(footer);

        currentMethod = null;

        return builder.toString();
    }